ProspectIQ

A modular command-line pipeline that collects publicly available lead information, normalizes it into one record format, enriches it, scores it with explainable signals, and exports it with its provenance intact.

Python CLI · source not currently public

My role

Designed and built the CLI pipeline, its schema, enrichment and scoring logic, and its test and CI setup.

ProspectIQ wordmark surrounded by lead-scoring interface panels.
Source modules
8Social, developer, video, and link-in-bio platforms.
Automated tests
272Collected from the project source (Sep 2026 snapshot).
Python versions in CI
33.10, 3.11, and 3.12 on GitHub Actions.

The problem

Useful lead information is spread across social profiles, developer platforms, video channels, company websites, and link-in-bio pages, each with different field names, data types, and limits. Combining it into a trustworthy dataset takes more than copying names into a spreadsheet.

Many enrichment tools return a contact with an opaque confidence score, so the user cannot tell whether an address was publicly observed, inferred from a pattern, guessed, or verified. I wanted every result to keep its origin visible.

My contribution

I built ProspectIQ as a personal open-source project: the source modules, the normalization boundary, the enrichment and verification pipeline, the scoring model, the CSV exporter, and the testing and CI setup.

What I built

ProspectIQ runs as a sequence of independent stages. Source modules collect public information, one normalization boundary turns every response into a single Lead model, and an enrichment layer looks for stronger contact and company signals. Each final record carries its email source, confidence, verification status, company domain, score, original platform, and collection time.

  • Source modules for social, developer, video, and link-in-bio platforms behind one CLI and interactive menu.
  • Website and domain enrichment, email-pattern inference, optional SMTP verification, and catch-all detection.
  • A documented 0–100 lead score in which every point maps to a named signal.
  • A stable, spreadsheet-safe CSV export with provenance fields and formula-injection protection.

How it works

Each stage depends only on the structured result of the stage before it, so platform-specific complexity stays inside the source modules.

  1. CLI input
  2. Source scrapers
  3. Normalized Lead model
  4. Website + domain enrichment
  5. Email candidate verification
  6. Lead scoring
  7. CSV export
Collection

Source modules share an HTTP layer, central configuration, conservative pacing, typed errors, and a declarative source registry.

Normalization

Lead.from_raw maps aliases, coerces inconsistent types, and preserves unmodeled fields so every later stage receives the same shape.

Quality

pytest without live network dependencies, Ruff, mypy, and GitHub Actions across supported Python versions.

Seven-stage pipeline diagram from CLI input to CSV export, with notes on provenance, observed versus inferred data, and responsible limits.
The pipeline as documented in the project: every stage reads the structured record produced by the stage before it.

Key decisions

Preserve provenance instead of presenting guesses as facts.

An address found in a public bio is treated differently from one inferred from a company's naming pattern, and the export says which is which.

Use one normalization boundary.

Source modules may return platform-specific data, but only one function translates it, which keeps platform assumptions out of every later stage.

Keep the registry as the single source of truth.

The CLI, interactive menu, and source listing all read one registry, so adding a source means one module and one entry.

Build responsible-use limits into the system.

ProspectIQ does not solve CAPTCHAs, evade blocks, access private data, or send messages; it stops at access restrictions and rate limits.

Tradeoffs

Coverage vs. reliability: More sources add value, but public pages change. Typed errors and source isolation keep one failure from corrupting the dataset.

Usefulness vs. certainty: Inferred addresses are useful candidates but not confirmed contacts, so uncertainty is preserved instead of collapsed into valid or invalid.

Outcomes & evidence

ProspectIQ became one workflow instead of a set of disconnected scrapers: collection, normalization, enrichment, scoring, and export through a single command-line interface, with an offline demo and automated tests.

Scope & limits

The public GitHub repository that previously hosted ProspectIQ is not currently available, so this page does not link to source code. The figures above were re-checked against the project's own source snapshot from September 2026.

What I learned

When several sources contribute to one record, normalized structure and visible provenance matter more than raw volume.

Built with

PythonHTTPXRichdnspythonpytestRuffmypyGitHub Actions

More projects

All projects