Skip to main content

Free, open-source Apollo alternative: find anyone, verify deliverably (7-signal engine), write and send cold email — local-first, keyless, $0. Pluggable public-data sources, a chat CLI, and a local web dashboard.

Project description

🧲 OpenLeads

Apollo for everyone. For $0.

Find founders, developers, doctors, researchers — anyone — verify their email deliverably, write the cold email, and send it. Free, open source, keyless, and entirely on your machine.

License: PolyForm NC Python 3.8+ Zero-dependency core PyPI CI PRs Welcome Stars


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 → sent machine, fed by a registry of pluggable, keyless, public data sources — running entirely on your laptop.

v3 is the ultimate update. v2 found and verified leads. v3 closes the loop: it writes the email and sends it, behind a deliverability engine that beats Hunter & Apollo's free tier — all for $0, with a zero-dependency core, and no data ever leaving your machine.

$ openleads run "50 AI founders in SF, verified only" --live
  [engine] source=yc — searching…
   safe   ada@acme.ai        Ada Lovelace · Founder · 96
   safe   grace@cobol.dev    Grace Hopper · CEO     · 91
   risky  j.doe@stealth.io   J. Doe       · —       · 58   (held back)
  [engine] done — 41 safe · 9 risky
  [write]  drafting 41 personalized emails…
  [outbox] sender grade A · warmup day 6 · 40/day
   sent   → ada@acme.ai   «quick idea re: your launch»
  → 40 sent · 1 held (cap) · 0 bounced

✨ The four clicks

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 who you want in plain English. Keyless public sources → resolved 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.

Do it in the terminal (openleads run …), in the chat REPL (openleads), or in the local web dashboard (openleads web).

🖥️ 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.0.0. Full walkthrough: docs/quickstart.md.

⚡ Commands

# find + verify (deliverable only)
openleads find "50 fintech founders, verified only" --out leads.csv
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

# 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.

💬 The chat CLI

openleads chat (or just openleads) opens a Claude-Code-style REPL. Type in plain English and refine conversationally — now with /write and /send too:

openleads> pediatricians in California, verified only
openleads> /source github
openleads> machine learning researchers as ndjson
openleads> /write          # draft emails for the safe leads
openleads> /send --live    # send them (with a confirm)

Works fully offline via a rule-based parser (no key needed). Set OPENROUTER_API_KEY (a free model works) to upgrade free-form parsing and AI drafting.

🧩 Sources (and adding your own)

$ openleads sources
  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.1 — better leads, faster. hn mines Hacker News' monthly "Who is hiring?" thread for companies hiring right now — real domains and, very often, direct apply emails that land as safe instantly. The github source was rebuilt to return real, contactable developers (no more topic/org junk), and the engine now resolves emails concurrently and fails fast with a clear message instead of grinding for minutes. Try: openleads find --source hn -n 25.

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/bad tiers
  • 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

openleads-3.1.0.tar.gz (166.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

openleads-3.1.0-py3-none-any.whl (133.6 kB view details)

Uploaded Python 3

File details

Details for the file openleads-3.1.0.tar.gz.

File metadata

  • Download URL: openleads-3.1.0.tar.gz
  • Upload date:
  • Size: 166.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for openleads-3.1.0.tar.gz
Algorithm Hash digest
SHA256 b1ce7c669857ab1e418be71e124054e44d39e393ee51c4c6b17f15c85dbd816f
MD5 ba220d41a03b3e9cc351f3e03289af99
BLAKE2b-256 0380c7ce5f8aa929b0649e1819c7f72a715def10513881e9def803686827c637

See more details on using hashes here.

File details

Details for the file openleads-3.1.0-py3-none-any.whl.

File metadata

  • Download URL: openleads-3.1.0-py3-none-any.whl
  • Upload date:
  • Size: 133.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for openleads-3.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b375ce39abc6caaecd523ce333e4d17897f3222e97b1d9688a72aeedd741254d
MD5 01728b4751259a9746fade480d6d9554
BLAKE2b-256 8b9153e3c6833377efc574f1feccdb05a2f90fc63cfec4c4001cc8903a3a1c9e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page