AI Company Enrichment - Website to Firmographics
Pricing
from $20.00 / 1,000 company enricheds
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
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
6 days ago
Last modified
Categories
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}
| Field | Source | Meaning |
|---|---|---|
website, finalUrl | input / HTTP | What you passed and where it redirected (notion.so -> notion.com) |
companyName, tagline, description | LLM, falls back to JSON-LD / OG / title | Name as the company writes it, its own one-liner, a 1-2 sentence factual summary |
industry | LLM | One of 30 fixed values (list below), so you can group and filter |
subIndustry | LLM | Short free text, e.g. "Online brokerage and trading platform" |
businessModel | LLM | B2B / B2C / B2B2C / marketplace / agency / nonprofit / other |
whatTheySell, targetCustomer | LLM | One sentence each |
companySizeBand, sizeReasoning | LLM | 1-10 / 11-50 / 51-200 / 201-1000 / 1000+ plus the signal it used. Always an estimate |
pricingModel, hasFreeTrial | LLM | free / freemium / subscription / one-time / usage / quote / unknown; trial = time-limited trial, not a free plan |
notableProducts, keywords | LLM | Up to 5 products as named on the site; 10 lowercase keywords |
confidence | LLM | 0-1, how well the pages support the record as a whole |
evidence | LLM, verified | One key per judgment field: a verbatim quote (<=160 chars) or a page URL. Quotes not present in the crawled text are replaced with null |
techStackHints | deterministic | 50 fingerprints: Shopify, WordPress, Webflow, Next.js, HubSpot, Intercom, Stripe, gtag/GTM, Segment, Meta Pixel, Greenhouse, Lever, Ashby, Cloudflare... |
emails, phones | deterministic | From visible text and mailto: / tel: links across the fetched pages, max 10 each |
socials | deterministic | linkedin, twitter/x, github, youtube, instagram, facebook (null when absent) |
addressHints, country, countrySource | deterministic | JSON-LD address, then phone country code, then TLD. countrySource says which |
language | deterministic | <html lang> |
openRolesCount | deterministic | Distinct job links (or "N open roles" text) on the careers page; null when the board is JS-rendered |
blogLastPostDate | deterministic | Newest date on the blog index (<time>, published-time meta, JSON-LD, dates in text); heuristic |
careersUrl, pricingUrl, contactUrl, aboutUrl, blogUrl | deterministic | Key pages found on the homepage (external ATS boards count as careers) |
pagesFetched, pagesSkipped | crawl | What was read; skips carry the reason (robots.txt, HTTP error) |
metaDescription, pageTitle | deterministic | Raw homepage meta, kept for auditing |
llmModel, enrichedAt | run | Which model answered, when |
rawText | with includeRawText | The extracted text of every page, for auditing |
enrichment_error | run | null 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}
| Field | Default | Notes |
|---|---|---|
websites | required (or companyNames) | Homepage URLs or bare domains. Duplicates are removed |
companyNames | [] | Best effort: resolves the homepage via a DuckDuckGo search for " |
pagesToCrawl | 6 (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 |
llmProvider | apify-managed | apify-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-mini | BYOK 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 |
includeRawText | false | Attach every page's extracted text to the row (large) |
maxItems | all | Stop after this many companies |
maxConcurrency | 5 | Companies in parallel; pages within a company are fetched one at a time |
proxyConfiguration | Apify datacenter | Use residential for sites that block datacenter IPs |
Pricing
Pay per event:
| Event | Price |
|---|---|
| Actor start | $0.005 per run |
| Company enriched | $0.02 per successful row |
| Company failed | free |
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. companySizeBandis an estimate from what the site says (team page, "N employees", customer counts, open roles). ReadsizeReasoning. It is not a headcount from a registry.pricingModelandhasFreeTrialdepend on a reachable pricing page. Sites without one usually getquoteorunknown.- Country is a hint (JSON-LD address, phone prefix, TLD), not the legal HQ.
.comsites without a phone or address getnull. blogLastPostDateis 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.txtis honoured, so disallowed key pages are skipped and listed inpagesSkipped. - Company names are resolved through a web search and can pick the wrong site for ambiguous names. Verify
websitein the row. - One LLM call per company. Model output is schema-validated and retried once; a second invalid answer produces
enrichment_errorstarting withLLM.
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.jsonexport OPENAI_API_KEY=... # managed-mode key for local runs (optional: OPENAI_BASE_URL, OPENAI_MODEL)apify run --purge # or: npm startnpm test # offline extractor + validator checks, then a live crawl (skips offline); LLM check runs only with OPENAI_API_KEYLLM_DRY_RUN=1 apify run --purge # deterministic pass only, LLM fields null, rows flagged llmDryRunACTOR_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.