Most of what B2B enrichment vendors sell is information companies publish about themselves, for free, on their own websites. What you’re paying per-credit prices for is mostly the reading.
I noticed this while burning through enrichment credits on accounts that turned out to be obvious non-fits — agencies when I needed SaaS, enterprise when I needed SMB. The data that would have disqualified them in seconds (what they sell, who they sell to, how they price) was sitting on their homepages the whole time. No vendor needed. Just reading.
So I did the obvious thing: pointed an LLM at company websites and made it fill out a fixed schema. This post covers what that looks like, what it costs (spoiler: about a cent per company), and the failure modes I hit building it into a production tool.
What you can extract from a website alone
More than you’d guess. From the homepage plus three or four key pages (/about, /pricing, /careers, /contact), reliably:
- Identity: name, one-line description, industry
- Business model: B2B SaaS vs. ecommerce vs. agency vs. marketplace — the single most useful ICP filter
- Who they sell to: an ICP summary inferred from their own positioning
- Pricing model: freemium / subscription / usage-based / “book a demo” — and visible tiers. “Book a demo” vs. self-serve alone tells you a lot about deal size
- Tech stack hints: integrations and technologies they mention
- Hiring signals: careers page contents — hiring roles are spend commitments, which makes them intent data
- Contacts and socials: generic emails (info@, sales@), phone numbers, social links
- Firmographics: HQ location, founded year, a size estimate
Here’s a real extraction — I ran it against apify.com as a test:
{
"domain": "apify.com",
"companyName": "Apify",
"industry": "Technology",
"businessModel": "B2B SaaS",
"pricingModel": "subscription",
"icpSummary": "Individuals, startups, and large enterprises looking for web data solutions and automation tools.",
"employeeCountEstimate": "51-200",
"hqLocation": "Prague, Czech Republic",
"isHiring": true,
"contactEmails": ["[email protected]"],
"techStackHints": ["Python", "JavaScript", "TypeScript"],
"confidence": 0.9
}
Enter fullscreen mode Exit fullscreen mode
Every field came from their own pages. Nothing purchased, nothing stale.
The architecture (it’s short)
- Fetch the homepage. Plain HTTP — most marketing sites don’t need a headless browser.
- Parse internal links and pick the useful pages by URL pattern: about, pricing, careers, contact, product.
- Strip the HTML to text, concatenate with page labels, truncate to a sane token budget.
- One LLM call with a strict JSON schema and a hard rule: never invent — use null/”unknown” when absent.
- Validate the JSON, attach the source URLs, done.
With a small model (gpt-4o-mini class) the LLM step costs a fraction of a cent; with fetches included you land around a cent per company. Compare that to the $0.75–1.50 per row that credit-based AI enrichment effectively costs on paid plans.
Failure modes worth knowing before you build this
- Hallucinated firmographics. Rare but real — the model occasionally “remembers” a company instead of reading the page. The strict schema plus explicit permission to answer “unknown” kills most of it; keeping a confidence score exposes the rest.
- JS-only websites. Some sites render nothing without a browser. Accept the miss or add a headless fallback; I chose to accept the miss (error rows, clearly marked) to keep speed and cost down.
- Personal data temptation. Scraping personal emails puts you in GDPR territory for no good reason. Restrict extraction to generic company addresses (info@, sales@) — the compliance surface drops to almost nothing and, honestly, generic inboxes are where cold email belongs anyway.
- Redirect chains and www quirks. Boring, but half your early failures will be URL normalization.
If you’d rather not maintain it
I packaged mine as an Apify Actor: AI Company Enrichment. Disclosure: I built it, pay-per-company, and everything above is how it works internally — so if you want to own the pipeline, this post is the spec.
Called via API:
curl -X POST "https://api.apify.com/v2/acts/benedictmendoza~ai-company-enrichment/runs?token=$APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"companies": ["stripe.com", "notion.so", "yourprospect.com"]}'
Enter fullscreen mode Exit fullscreen mode
It slots into the usual places: a Clay table’s HTTP enrichment column (do the cheap firmographic pass first, spend real credits only on accounts that pass ICP fit), an n8n/Make workflow between “new lead” and “score lead,” or just a CSV in, CSV out.
The general principle
Split your enrichment bill in two: data that genuinely requires a vendor (verified emails, direct dials, funding data) and data that’s self-published on the prospect’s website. Pay vendors for the first category. Read the second one yourself — with an LLM, “yourself” now costs a cent and takes eight seconds.
If you try the Actor and want extra fields extracted, the Issues tab reaches me directly — field requests are cheap to ship.