Free, open-source Apollo alternative: one search box federates across free public sources (local businesses via OpenStreetMap, startups, companies, developers), finds the people, verifies emails deliverably, and automates outreach (recipes, sequences, exports) — plus bring-your-own-list enrichment. Local-first, keyless, $0.
Project description
🧲 OpenLeads
Apollo for everyone. For $0.
One search box. Describe your ideal customer — "marketing agencies in Miami", "fintech founders", "dentists in Austin" — and OpenLeads federates across free public sources, finds the real people, verifies their email, and automates the outreach. Open source, keyless, entirely on your machine.
Apollo, Hunter, RocketReach, and ZoomInfo sell the same two things: a contact database and email verification — then upsell you the sending. OpenLeads is the whole stack, inverted and free.
A universal
entity → verified email → cold email → sentmachine, fed by a registry of pluggable, keyless, public data sources — running entirely on your laptop.
v4 makes the lead-gen great. Earlier versions found and sent; the weak link was discovery — you had to pick a source, and most were narrow. v4 rebuilds discovery as a federated waterfall: one query fans out across the public sources that fit it, finds the people behind each company, verifies their email, and dedupes — the way Apollo and Clay actually work, free and local. The headline new source is local businesses via OpenStreetMap — the long tail (agencies, clinics, firms, shops) that paid tools charge the most for.
$ openleads find "marketing agencies in Miami"
[engine] federated search · local …
safe hello@brightspark.com Bright Spark Marketing · 98%
risky jane.lee@brightspark.com Jane Lee · Founder & CEO · 62%
safe crystalei@marketkarma.com Crystalei Daniels · Head of Growth · 98%
[engine] done — real businesses, their people, verified emails
$ openleads run "50 fintech founders, verified only" --live
[engine] federated search · yc · hn …
safe ada@acme.ai Ada Lovelace · Founder · 96%
[write] drafting 41 personalized emails… · [outbox] grade A · warmup day 6
→ 40 sent · 1 held (cap) · 0 bounced
✨ How it works
The painful multi-tool workflow — scrape in A, verify in B, enrich in C, load into sender D, warm up in E — collapses into one local app + CLI:
| 1 · Find | Describe your ICP in plain English. | Federates across local businesses (OpenStreetMap), startups, companies, and developers — finds the people, resolves emails. |
| 2 · Write | Personalized, spam-linted, plain-text drafts. | Free LLM or sharp template — edit anything. |
| 3 · Connect | One-time mailbox setup with provider presets. | A preflight grades your SPF/DKIM/DMARC. |
| 4 · Send | Throttled, warmup-capped, suppression-aware. | One-click unsubscribe headers. No tracking pixels. |
Already have a list? Enrich it — openleads enrich list.csv runs the same waterfall over your own names/companies/domains. Want it hands-free? Save a recipe (openleads recipe add …) and the on-device scheduler runs find → write → send → export daily, pausing anyone who replies.
Do it in the terminal (openleads find …), in the chat REPL (openleads), or in the local web dashboard (openleads web).
🛰️ Where leads come from — the federation
One query, many sources, merged and de-duplicated. You never pick a source (but -s name still pins one):
| Source | Vertical | Keyless |
|---|---|---|
local |
Local businesses by category + city (OpenStreetMap/Overpass) — agencies, clinics, firms, gyms, shops | ✅ |
yc · hn |
Startup founders (Y Combinator) · companies hiring now (Hacker News) | ✅ |
companies · edgar |
Companies by industry/country (Wikidata) · US public companies (SEC EDGAR) | ✅ |
github · openalex · npi |
Developers · researchers · US healthcare providers | ✅ |
domains |
Hunter-style: real published emails for any domain you name | ✅ |
Each company is expanded into real decision-makers via team-page discovery, then every address goes through the email waterfall (ground-truth harvest → learned pattern → permutation → MX/SMTP/Gravatar consensus → calibrated 0–100 confidence).
🖥️ The local dashboard
openleads web # opens http://127.0.0.1:8787 — no Node, no build, no cloud
A hand-built single-page app served by a stdlib HTTP server bound to localhost. Find, Leads, Compose, Send, CRM, Settings, and Doctor — with the four-click path front and centre and results streaming in live. Black-and-white with hints of red, reduced-motion aware, and nothing leaves your machine. See docs/web.md.
📡 Why the emails actually land
Most free finders verify with a single SMTP RCPT probe over outbound port 25 — which home ISPs and most clouds block. When it's blocked, every address silently degrades to a first.last@domain guess and your campaign bounces. That was v2's #1 failure.
v3 cross-checks seven independent signals — most needing no port 25 at all — then gates honestly into three tiers so you only send what's likely to land:
| Signal | Needs port 25? |
|---|---|
| MX consensus — two DoH resolvers must agree | no |
| SPF · DMARC · provider class — TXT lookups | no |
| Disposable / role / free-provider — static lists | no |
| Gravatar existence — md5 → 200/404 | no |
Ground-truth harvest — real emails from GitHub commits, mailto:, security.txt |
no |
| Learned domain patterns — compound across every run | no |
SMTP RCPT + catch-all double-probe |
yes (graceful when blocked) |
→ safe (send it) · risky (kept, held back by default) · bad (dropped). Every lead carries an explainable 0–100 score and a reasons[] list. Deep dive: docs/deliverability.md.
🆚 vs. the free tiers
| OpenLeads | Apollo / Hunter (free) | |
|---|---|---|
| Cost | $0, forever | credit-limited, then paid |
| API key required | ❌ none | ✅ required |
| Who you can find | founders, devs, doctors, researchers + any vertical you plug in | their database only |
| Email verification | ✅ 7-signal consensus + 0–100 score | paid feature |
| Writes the email | ✅ free LLM or template | ❌ / upsell |
| Sends it for you | ✅ warmup, throttle, suppression | upsell |
| Where it runs | 🔒 your machine, no data leaves | their cloud |
| You own the code | ✅ readable, hackable | ❌ black box |
| Core dependencies | zero (stdlib only) | — |
🚀 Install
# Python (recommended) — zero-dependency engine + the full local app
pip install "openleads[all]"
# minimal: just the engine + plain CLI
pip install openleads
Prefer Node? A thin wrapper runs it via npx (it installs the Python package on first use):
npx openleads find "50 fintech founders verified only"
# or: npm i -g openleads
Try it in 10 seconds:
pip install "openleads[all]"
openleads doctor # check your finding + sending setup
openleads web # launch the local dashboard
# …or stay in the terminal:
openleads # the interactive chat — just type what you want
openleads --version should print openleads 3.5.0. Full walkthrough: docs/quickstart.md.
⚡ Commands
# find + verify — every lead carries a calibrated Confidence %
openleads find "50 fintech founders, verified only" --out leads.csv
openleads find "emails at stripe.com" # Hunter-style domain search
openleads find --source npi --keyword pediatric --location CA --format json
# the whole pipeline: find → write → send (dry-run unless --live)
openleads run "rust developers in Berlin"
openleads run "20 SaaS founders" --live
# one-line natural-language campaign (free, no key needed)
openleads assistant "send 50 emails to fintech founders for my SaaS at 9am"
# automation — your machine sends for you
openleads schedule --at 09:00 # install a daily on-device drip (launchd/cron)
openleads drip --live # run one cycle now (due campaigns + follow-ups)
# pieces of it
openleads write "10 AI founders" -o drafts.json # just draft
openleads send "10 AI founders" --live # find → write → send
openleads verify ada@acme.io grace@cobol.dev # verify concrete addresses
# manage
openleads sources # what you can search
openleads crm # your local CRM (leads + touches + status)
openleads config # set keys, mailbox, sender identity, send limits
openleads doctor # health-check finding + sending
openleads inbox # scan IMAP for replies & bounces (optional)
Sending is dry-run by default everywhere — add --live to actually send. The finder never touches your mailbox. Real sends are also saved to your IMAP Sent folder so they show up in your mail client (configurable via save_to_sent).
💬 The chat CLI
openleads chat (or just openleads) opens a Claude-Code-style REPL. Type in plain English — it finds, or, when you ask to send/schedule, configures the whole campaign:
openleads ❯ pediatricians in California, verified only
openleads ❯ emails at stripe.com
openleads ❯ send 30 emails to rust developers in Berlin for my dev tool at 9am
openleads ❯ /schedule 09:00 # run it unattended, daily
openleads ❯ /send live # …or deliver the previewed batch now
Works fully offline via a rule-based parser (no key needed). Set OPENROUTER_API_KEY (a free model works) to upgrade free-form understanding and AI drafting.
🧩 Sources (and adding your own)
$ openleads sources
domains [company] any company domain (Hunter-style email search)
github [people ] developers & open-source orgs
hn [company] companies hiring now (Hacker News)
npi [people ] U.S. doctors & healthcare providers
openalex [people ] researchers & academics
producthunt [company] trending products & startups
yc [company] startup founders (Y Combinator)
New in v3.5 — the leads actually work. Ground-truth harvesting now runs by default: OpenLeads reads a company's own published addresses to learn its email pattern, so a real sibling address promotes every coworker to an evidence-backed
safe— the free analogue of Hunter's domain search, also exposed directly as the newdomainssource (openleads find "emails at stripe.com"). Every lead carries a calibrated Confidence %, port 25 is probed once (not per lead, so searches are fast even when it's blocked), and a free assistant turns "send 50 emails to X at 9am" into a scheduled, on-device campaign.
All keyless and free. Want a vertical we don't ship — recruiters, lawyers, real-estate agents, your CRM export? Drop a *.py file in ~/.openleads/sources/:
from openleads.sources.base import Source
from openleads.models import Entity, Query
class LawyersSource(Source):
name, kind, vertical = "lawyers", "people", "attorneys"
description = "State bar directory."
def search(self, query: Query):
for row in fetch_from_some_free_directory(query):
yield Entity(full_name=row["name"], organization=row["firm"],
domain=row["firm_domain"], source=self.name)
Run openleads sources and it's there. The email engine handles the rest. Guide: docs/sources.md.
🔒 Local-first by design
No hosted backend. No accounts. No tracking. Your leads, drafts, mailbox credentials, learned patterns, and CRM all live in a local SQLite file under ~/.openleads. The engine talks only to public data sources and your mail server. Secrets are stored chmod 600 and never sent back to the browser.
🔍 How it works
flowchart LR
Q[Your request<br/>chat · CLI · web] --> I[Intent parser<br/>rule-based ± free LLM]
I --> S[Source plugin<br/>yc · github · npi · openalex · …]
S --> E[Deliverability engine<br/>7 signals → score → tier]
E --> W[Compose<br/>spam-linted draft]
W --> P[Preflight<br/>SPF/DKIM/DMARC + warmup]
P --> D[Send<br/>throttled · suppression-aware]
D --> C[(Local SQLite<br/>CRM · patterns · cache)]
E <--> C
Same path is invoked by the CLI, the chat REPL, and the web dashboard. Architecture: docs/architecture.md.
🧭 Responsible use
OpenLeads is for legitimate outreach, recruiting, research, and prospecting. Some verticals carry extra weight — healthcare providers (NPI), academics — so please read docs/responsible-use.md. You are responsible for anti-spam law (CAN-SPAM, GDPR, CASL) and each source's terms. v3 ships the guardrails (suppression, one-click unsubscribe, warmup caps, dry-run defaults); using them well is on you.
🗺️ What's new in v3.0
- ✅ Multi-signal deliverability engine — 7 signals, mostly no port 25, honest
safe/risky/badtiers - ✅ Writes + sends — drafting, provider presets, preflight, warmup, suppression, follow-ups
- ✅
openleads run— find → verify → write → send in one command - ✅ Local web dashboard (
openleads web) — no Node, no cloud - ✅ In-app config +
doctor— no dotfile editing - ✅ Local CRM, dedupe, learned patterns that compound across runs
See the full CHANGELOG.
🤝 Contributing
PRs very welcome — see CONTRIBUTING.md. The highest-impact contribution is a new source plugin (guide) — that's literally how OpenLeads becomes "Apollo for everyone."
📄 License
PolyForm Noncommercial 1.0.0 — free for personal, research, educational, and nonprofit use. Commercial use? See COMMERCIAL-LICENSE.md.
🙏 Acknowledgements
yc-oss/api · OpenAlex · NPI Registry · GitHub & ProductHunt public data · Gravatar · and everyone who has ever rage-quit a "request a demo" button.
If OpenLeads saved you a subscription, consider leaving a ⭐ — it genuinely helps.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file openleads-4.0.1.tar.gz.
File metadata
- Download URL: openleads-4.0.1.tar.gz
- Upload date:
- Size: 243.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9541278a63bf128997a63e40103329f113f29b83942efaa6e2368f04cdd3839d
|
|
| MD5 |
e7900a36244b1eabade8b18e3cea30b1
|
|
| BLAKE2b-256 |
e5dff7fca8e7c33d2e366dfb748981ff3c2e99bd1851ccb3eb326db2ca09d5e0
|
File details
Details for the file openleads-4.0.1-py3-none-any.whl.
File metadata
- Download URL: openleads-4.0.1-py3-none-any.whl
- Upload date:
- Size: 191.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
821a0f3301d95ac9f5c6009d2ecb2021a0da1c128d76f0e8fc0b1085cbc2762d
|
|
| MD5 |
1c1a67408b07f8cfaaf0e8a329243edd
|
|
| BLAKE2b-256 |
da207be6fa0c89add676b175c9541fea91e7bb679ce488298b7a9da746b169f1
|