AI Company Enrichment - Website to Firmographics avatar

AI Company Enrichment - Website to Firmographics

Pricing

from $20.00 / 1,000 company enricheds

Go to Apify Store
AI Company Enrichment - Website to Firmographics

AI Company Enrichment - Website to Firmographics

Turn a list of company websites into clean firmographics: industry, what they sell, who they sell to, size band, pricing model, contacts, socials, tech hints. One LLM-verified JSON record per company, every judgment with evidence.

Pricing

from $20.00 / 1,000 company enricheds

Rating

0.0

(0)

Developer

Swaraj Samant Singh

Swaraj Samant Singh

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

6 days ago

Last modified

Share

Turn a list of company websites into clean firmographics: industry, what they sell, who they sell to, size band, pricing model, contacts, socials, tech hints - JSON/CSV. One LLM-verified record per company with evidence.

The actor reads the company's own site (homepage + about, pricing, careers, contact, blog), pulls the hard facts deterministically (no model involved: emails, phones, social links, tech fingerprints, open roles, last blog post, language, country hints), then makes exactly one LLM call to fill the judgment fields. Every judgment field comes with evidence: a quote from the pages or the page URL. Quotes that do not actually appear in the crawled text are thrown away, so a null evidence entry tells you the value is the model's inference rather than something the site says.

Companies that cannot be fetched or classified get a row with enrichment_error. No guessed records, and no charge for them.

What you get per company

{
"website": "https://linear.app",
"finalUrl": "https://linear.app/",
"companyName": "Linear",
"tagline": "The product development system for teams and agents",
"description": "Linear provides a purpose-built system for modern product teams and AI agents to plan, build, and ship software products with speed and clarity.",
"industry": "Software & SaaS",
"subIndustry": "Product management and issue tracking software",
"businessModel": "B2B",
"whatTheySell": "Cloud-based product development and workflow tools that combine planning, issue tracking, and AI agents for software teams.",
"targetCustomer": "Software and product development teams at companies that need structured workflows to plan, build, and ship products.",
"companySizeBand": "201-1000",
"sizeReasoning": "Serving more than 40,000 companies and having 26 open roles suggests a mid-sized team; this is an estimate.",
"pricingModel": "subscription",
"hasFreeTrial": false,
"notableProducts": ["Linear Agent", "Triage Intelligence", "Code Intelligence", "Linear Insights", "Linear Asks"],
"keywords": ["product development", "issue tracking", "ai agents", "software teams", "planning", "workflow", "project management", "product tool", "triage intelligence", "linear agent"],
"techStackHints": ["Next.js", "React", "Cloudflare", "Ashby"],
"emails": ["hello@linear.app"],
"phones": [],
"socials": { "linkedin": null, "twitter": "https://x.com/linear", "github": "https://github.com/linear", "youtube": "https://www.youtube.com/@linear", "instagram": null, "facebook": null },
"addressHints": null,
"country": null,
"countrySource": null,
"language": "en",
"openRolesCount": 26,
"blogLastPostDate": "2026-08-13",
"careersUrl": "https://linear.app/careers",
"pricingUrl": "https://linear.app/pricing",
"contactUrl": "https://linear.app/contact",
"aboutUrl": "https://linear.app/about",
"blogUrl": "https://linear.app/insights",
"pagesFetched": ["https://linear.app/", "https://linear.app/about", "https://linear.app/pricing", "https://linear.app/careers", "https://linear.app/contact", "https://linear.app/insights"],
"confidence": 0.91,
"evidence": {
"tagline": "The product development system for teams and agents",
"whatTheySell": "A new species of product tool. Purpose-built for modern teams with AI workflows at its core, Linear sets a new standard for planning and building products.",
"companySizeBand": "Our team is distributed across North America and Europe, and we're continuing to grow internationally.",
"hasFreeTrial": "Pricing Free $0 Free for everyone",
"targetCustomer": null,
"...": "one key per judgment field"
},
"llmModel": "gpt-4o-mini",
"enrichedAt": "2026-08-18T10:12:41.126Z",
"enrichment_error": null
}
FieldSourceMeaning
website, finalUrlinput / HTTPWhat you passed and where it redirected (notion.so -> notion.com)
companyName, tagline, descriptionLLM, falls back to JSON-LD / OG / titleName as the company writes it, its own one-liner, a 1-2 sentence factual summary
industryLLMOne of 30 fixed values (list below), so you can group and filter
subIndustryLLMShort free text, e.g. "Online brokerage and trading platform"
businessModelLLMB2B / B2C / B2B2C / marketplace / agency / nonprofit / other
whatTheySell, targetCustomerLLMOne sentence each
companySizeBand, sizeReasoningLLM1-10 / 11-50 / 51-200 / 201-1000 / 1000+ plus the signal it used. Always an estimate
pricingModel, hasFreeTrialLLMfree / freemium / subscription / one-time / usage / quote / unknown; trial = time-limited trial, not a free plan
notableProducts, keywordsLLMUp to 5 products as named on the site; 10 lowercase keywords
confidenceLLM0-1, how well the pages support the record as a whole
evidenceLLM, verifiedOne key per judgment field: a verbatim quote (<=160 chars) or a page URL. Quotes not present in the crawled text are replaced with null
techStackHintsdeterministic50 fingerprints: Shopify, WordPress, Webflow, Next.js, HubSpot, Intercom, Stripe, gtag/GTM, Segment, Meta Pixel, Greenhouse, Lever, Ashby, Cloudflare...
emails, phonesdeterministicFrom visible text and mailto: / tel: links across the fetched pages, max 10 each
socialsdeterministiclinkedin, twitter/x, github, youtube, instagram, facebook (null when absent)
addressHints, country, countrySourcedeterministicJSON-LD address, then phone country code, then TLD. countrySource says which
languagedeterministic<html lang>
openRolesCountdeterministicDistinct job links (or "N open roles" text) on the careers page; null when the board is JS-rendered
blogLastPostDatedeterministicNewest date on the blog index (<time>, published-time meta, JSON-LD, dates in text); heuristic
careersUrl, pricingUrl, contactUrl, aboutUrl, blogUrldeterministicKey pages found on the homepage (external ATS boards count as careers)
pagesFetched, pagesSkippedcrawlWhat was read; skips carry the reason (robots.txt, HTTP error)
metaDescription, pageTitledeterministicRaw homepage meta, kept for auditing
llmModel, enrichedAtrunWhich model answered, when
rawTextwith includeRawTextThe extracted text of every page, for auditing
enrichment_errorrunnull on success; otherwise the reason and the row has no other fields

Industry taxonomy (30): Software & SaaS, IT Services & Consulting, Cybersecurity, Data & Analytics, AI & Machine Learning, Developer Tools & Infrastructure, Fintech & Financial Services, Banking & Insurance, E-commerce & Retail, Consumer Goods, Marketing & Advertising, Media & Entertainment, Education & EdTech, Healthcare & Life Sciences, Biotech & Pharma, Real Estate & PropTech, Construction & Engineering, Manufacturing & Industrial, Energy & Utilities, Transportation & Logistics, Travel & Hospitality, Food & Beverage, Agriculture, Legal & Compliance, HR & Recruiting, Telecommunications, Gaming, Nonprofit & Government, Professional Services, Other.

Input

{
"websites": ["https://www.notion.so", "linear.app", "zerodha.com"],
"pagesToCrawl": 6,
"llmProvider": "apify-managed",
"model": "gpt-4o-mini",
"includeRawText": false
}
FieldDefaultNotes
websitesrequired (or companyNames)Homepage URLs or bare domains. Duplicates are removed
companyNames[]Best effort: resolves the homepage via a DuckDuckGo search for "
pagesToCrawl6 (max 8)Homepage plus up to N-1 of about, pricing, careers, contact, blog, in that priority. Total text capped at 150 KB per company, 12k characters sent to the model
llmProviderapify-managedapify-managed: the actor's own key, LLM cost is included in the per-company price. byok: your key, your bill
openaiApiKey, openaiBaseUrl, model- / https://api.openai.com/v1 / gpt-4o-miniBYOK only. Any OpenAI-compatible /v1/chat/completions endpoint that supports response_format: json_object works: OpenAI, Azure OpenAI (https://<resource>.openai.azure.com/openai/v1, deployment name as model), OpenRouter, Groq, Together, a local Ollama behind a tunnel
includeRawTextfalseAttach every page's extracted text to the row (large)
maxItemsallStop after this many companies
maxConcurrency5Companies in parallel; pages within a company are fetched one at a time
proxyConfigurationApify datacenterUse residential for sites that block datacenter IPs

Pricing

Pay per event:

EventPrice
Actor start$0.005 per run
Company enriched$0.02 per successful row
Company failedfree

100 companies = about $2.00. On managed mode that price includes the LLM call (roughly 3-4k input tokens and a few hundred output tokens per company on gpt-4o-mini). With byok the LLM tokens go on your own bill and the per-company price still applies. Set "Maximum total charge" on the run to cap spend; the actor stops cleanly at the cap and you keep every row already written.

How this differs from other enrichment actors on the store

Most "company enrichment" actors return data from third-party databases (Crunchbase-style records, LinkedIn headcount, WHOIS, funding), or wrap a paid enrichment API. Those are the right tool when you need revenue, funding rounds or verified employee counts. This actor is different on purpose:

  • Source is the company's own website, read live. No stale database, no login, no browser. Small and new companies that databases have never heard of still get a full record.
  • Judgment fields are separated from facts, and every judgment carries evidence. You can see exactly which sentence made the model say "B2B" or "subscription", and null evidence flags inference.
  • Fixed taxonomy for industry, business model, size band and pricing model, so the output is filterable without post-cleaning.
  • Tech, hiring and content-freshness signals (techStackHints, openRolesCount, blogLastPostDate) that databases rarely have.
  • Honest on failure. Unreachable or JS-only sites produce enrichment_error, not a filler row, and are not charged.

It does not return revenue, funding, founding year, verified employee counts or executive contacts. Use a database-backed actor for those.

Limitations

  • JS-only sites. Pages that render everything client-side give little text; the model then works from title/meta and confidence drops. Careers boards embedded as JavaScript widgets return openRolesCount: null.
  • companySizeBand is an estimate from what the site says (team page, "N employees", customer counts, open roles). Read sizeReasoning. It is not a headcount from a registry.
  • pricingModel and hasFreeTrial depend on a reachable pricing page. Sites without one usually get quote or unknown.
  • Country is a hint (JSON-LD address, phone prefix, TLD), not the legal HQ. .com sites without a phone or address get null.
  • blogLastPostDate is a heuristic over dates found on the blog index; a page that prints today's date can shift it.
  • Bot protection. Sites behind Cloudflare challenge pages or aggressive WAFs may return 403; try residential proxies. robots.txt is honoured, so disallowed key pages are skipped and listed in pagesSkipped.
  • Company names are resolved through a web search and can pick the wrong site for ambiguous names. Verify website in the row.
  • One LLM call per company. Model output is schema-validated and retried once; a second invalid answer produces enrichment_error starting with LLM.

FAQ

Which pages does it read? The homepage, then the about, pricing, careers, contact and blog links found on it (in that priority) up to pagesToCrawl. pagesFetched lists them per row.

Can I trust the industry? It is one of 30 fixed values chosen by the model from the crawled text; evidence.industry shows the sentence it leaned on. Where the site is a thin landing page the model still has to pick something, so check confidence.

Can I use my own model? Yes, llmProvider: "byok" with openaiApiKey, openaiBaseUrl and model. Anything OpenAI-compatible with JSON mode works. Small models are fine for this task; the prompt is short and the output is validated.

Why is emails empty for a company that clearly has a contact form? Only addresses printed on the page or in mailto: links are collected. Forms, images and obfuscated addresses are not decoded.

How fast is it? About 5-15 seconds per company (6 pages fetched sequentially plus one LLM call), 5 companies in parallel. 100 companies take roughly 5 minutes.

Does it use a browser? No, plain HTTP with browser-like headers, which is why it runs on 256 MB.

Local development

npm install
# put your input in storage/key_value_stores/default/INPUT.json
export OPENAI_API_KEY=... # managed-mode key for local runs (optional: OPENAI_BASE_URL, OPENAI_MODEL)
apify run --purge # or: npm start
npm test # offline extractor + validator checks, then a live crawl (skips offline); LLM check runs only with OPENAI_API_KEY
LLM_DRY_RUN=1 apify run --purge # deterministic pass only, LLM fields null, rows flagged llmDryRun
ACTOR_TEST_PAY_PER_EVENT=1 ACTOR_MAX_TOTAL_CHARGE_USD=2.5 npm start # PPE cutoff: $1 per event, stops after start + one company

In production the managed key is set as a secret environment variable on the actor (OPENAI_API_KEY, optionally OPENAI_BASE_URL and OPENAI_MODEL); it never lives in the repository.