Skip to content

Latest commit

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

jmail-python

A simple, easy-to-use Python library for accessing the Jmail Data API, the public data API for the Jeffrey Epstein email archive.

No API keys. No rate limits. No authentication. Just data.

Installation

pip install jmail-python

Or with uv:

uv pip install jmail-python

Quick Start

fromjmailimportJmailClientclient=JmailClient()
# Get emails (slim = no body text, much faster)df=client.emails(slim=True)
print(df.head())
# Full emails with body textdf=client.emails()
# First 100 emails onlydf=client.emails(head=100)
# Document metadatadocs=client.documents()
# Documents with full extracted text (large download)docs=client.documents(include_text=True)

Available Datasets

MethodDatasetRecordsSize
client.emails()Emails (full)1.78M334 MB
client.emails(slim=True)Emails (slim)1.78M41 MB
client.documents()Documents1.41M25 MB
client.documents(include_text=True)Documents (full text)1.41MLarge
client.photos()Photos18K~1 MB
client.people()People473<100 KB
client.photo_faces()Photo Faces975<100 KB
client.star_counts()Star Counts414K~2 MB
client.release_batches()Release Batches11<10 KB
client.imessage_conversations()iMessage Conversations15<10 KB
client.imessage_messages()iMessage Messages4,509~172 KB

All methods return a pandas DataFrame. Pass head=N to any method to only load the first N rows.

Search and Analysis

client=JmailClient()
# Search emails by sender (case-insensitive)df=client.search_by_sender("ghislaine")
# Search by subjectdf=client.search_by_subject("flight")
# Top 10 most frequent senderstop=client.top_senders(n=10)
print(top)

Caching

The client uses ETag-based conditional requests to avoid re-downloading unchanged files.

  • Cache location: ~/.cache/jmail/
  • First download: saves the parquet file and its ETag
  • Subsequent requests: sends If-None-Match header, uses cache on 304 Not Modified
  • Disable: JmailClient(cache=False)
  • Clear: client.clear_cache()
# Always download fresh (no caching)client=JmailClient(cache=False)
# Custom cache directoryclient=JmailClient(cache_dir="/tmp/my-cache")
# Clear the cacheclient.clear_cache()

Direct URLs

Need raw URLs for use with DuckDB, Polars, or other tools?

client=JmailClient()
# Single dataset URLurl=client.url("emails-slim")
# -> "https://data.jmail.world/v1/emails-slim.parquet"url=client.url("emails-slim", fmt="ndjson.gz")
# -> "https://data.jmail.world/v1/emails-slim.ndjson.gz"# All dataset URLsall_urls=client.urls()

Manifest

The manifest provides dataset metadata and checksums:

client=JmailClient()
manifest=client.manifest()
print(manifest["version"])
print(manifest["datasets"]["emails"]["record_count"])

DuckDB Integration

You can query the parquet files directly over HTTP without downloading:

importduckdbresult=duckdb.sql(""" SELECT sender, COUNT(*) as n FROM read_parquet('https://data.jmail.world/v1/emails-slim.parquet') GROUP BY sender ORDER BY n DESC LIMIT 20""").df()
print(result)

Data Sources

The archive includes data from three sources:

  • House Oversight Committee releases
  • Department of Justice releases
  • Yahoo account releases

All data is public domain (US government records), served as static Parquet files from Cloudflare R2.

License

AGPL-3.0. See LICENSE for details.

About

Easy Python client for the Jmail Data API (Jeffrey Epstein email archive). No API keys, no rate limits, just data.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages