The imessage-analysis Python package provides query and analysis functions over an existing iMessage dataset. All functions return pyarrow.Table for seamless pandas integration.
pip install imessage-analysis- Python 3.11+
pyarrow(installed automatically)- macOS to build the dataset; query functions work on any platform if the Parquet dataset is already present
The Python package is query-only. It reads a dataset built by the CLI tool. Before using it, run:
imessage-analysis syncCalling imessage_analysis.sync() from Python will raise a RuntimeError — the Python interpreter does not have the required macOS Contacts permission, so any sync from Python would index messages but leave all names as phone numbers. Use the CLI to sync; use the Python package to query.
import imessage_analysis
# Returns pyarrow.Table — call .to_pandas() to convert
df = imessage_analysis.top_contacts(limit=10).to_pandas()
print(df)All functions return pyarrow.Table.
df = imessage_analysis.top_contacts(limit=20, year=2024).to_pandas()df = imessage_analysis.time_series(contact="Alice", window=7).to_pandas()
df = imessage_analysis.time_series(start="2023-01-01", end="2023-12-31").to_pandas()df = imessage_analysis.reactions().to_pandas()
df = imessage_analysis.reactions(contact="Alice", year=2024).to_pandas()df = imessage_analysis.effects(year=2024).to_pandas()df = imessage_analysis.links(limit=30).to_pandas()dow = imessage_analysis.seasonality(kind="dow").to_pandas()
monthly = imessage_analysis.seasonality(kind="month").to_pandas()df = imessage_analysis.contact_stats(limit=20).to_pandas()
df = imessage_analysis.contact_stats(contact="Alice").to_pandas()df = imessage_analysis.search_contacts("alice").to_pandas()Execute arbitrary SQL against the messages table.
df = imessage_analysis.query(
"SELECT year, COUNT(*) AS n FROM messages GROUP BY year ORDER BY year"
).to_pandas()import imessage_analysis
import pandas as pd
import matplotlib.pyplot as plt
df = imessage_analysis.query("SELECT * FROM messages").to_pandas()
df['timestamp'] = pd.to_datetime(df['timestamp'])
yearly = df.groupby('year').size()
yearly.plot(kind='bar', title='Messages per year')
plt.tight_layout()
plt.show()The Python package is built with maturin.
pip install maturin
cd crates/imessage-python
maturin develop --release