Company Data Enrichment — Firmographics, Revenue & HQ
Pricing
from $1.00 / 1,000 company records
Company Data Enrichment — Firmographics, Revenue & HQ
Enrich a list of company names or domains with clean firmographics: website, industry, HQ, employee count, revenue range, founded year, ownership & description as JSON. A low-cost ZoomInfo / Clearbit alternative for CRM enrichment, lead lists & sales intelligence.
Pricing
from $1.00 / 1,000 company records
Rating
5.0
(1)
Developer
Berkan Kaplan
Maintained by CommunityActor stats
3
Bookmarked
282
Total users
53
Monthly active users
6 days ago
Last modified
Categories
Share
Company Data Enrichment — Firmographics, Revenue & HQ ✨
🎉 Turn a list of company names, domains or Owler URLs into clean firmographics — website, industry, HQ address, founded year, employees, revenue band, ownership, CEO and description as one row per company. Built for CRM enrichment, lead scoring and account research.
🔍 What is Company Data Enrichment — and when should you use it?
Give this Actor company names, domains or Owler company URLs and it returns one firmographic record per company from the public company profiles on Owler. Names and domains are matched to a profile through Owler's own search suggestions; URLs are used as given. Every run reads the pages live.
Use it when you need: firmographics to fill gaps in a CRM or lead list (industry, size, revenue band, HQ, ownership); a short company profile before a sales call; the name, title and LinkedIn of the executive Owler lists as CEO.
Use something else when: you need registry-grade legal records (use a national company-registry Actor), email addresses or phone numbers (not in this output), or competitors, funding rounds and acquisitions — Owler Scraper returns those from the same source.
🤖 Use with AI agents
Already on the Apify MCP server? Ask for this Actor by name: foxlabs/company-enrichment.
Your agent can pay for its own runs. This Actor is pay-per-event with agentic payments, so an agent can discover it, run it and settle the bill over x402 (USDC on Base) or Skyfire — no Apify account or API token of its own. Billing is the same either way: per delivered company record — rows that only report a failed lookup are free from 25 September 2026.
Otherwise paste this into Claude, ChatGPT, Cursor or any MCP-enabled assistant:
I want company firmographics from the Apify Actor `foxlabs/company-enrichment`.Input: `companyNames` is a list of company names and `companyDomains` a list of domains (both are matched through Owler's search); `companyUrls` takes exact Owler company URLs. `maxResults` caps how many companies are looked up; a profile Owler doesn't have comes back as a free row with an `error` field (`includeUnmatched`, on by default).Start with: {"companyNames":["Stripe","Notion","Datadog"],"maxResults":100}Ask me what to look up, run the Actor, then summarise the rows as a table.
The machine-readable API, MCP config and OpenAPI definition live at apify.com/foxlabs/company-enrichment.md.
📋 Overview
Everything you need to enrich a company list — in one Actor, with no login, cookies or API key.
Why teams pick this Actor:
- ✅ Names, domains or URLs — use whatever your list has; a domain gives the most exact match.
- 🏢 Firmographics in one row — website, domain, industry, HQ and street address, founded year, employees, revenue band, ownership, CEO and description.
- 🧹 One row per company — inputs that resolve to the same Owler profile are fetched once.
- 💰 Pay per record — $0.001 per company record, no subscription.
- 🤖 Agent-ready — MCP + x402 agentic payments.
✨ Features
- 🔍 Three ways in —
companyNames,companyDomainsandcompanyUrls(Owler company URLs, or a .txt / .csv upload). - 🎯 Matching through Owler's search — in our test run
Notionresolved to Notion Labs, Inc. andDatadogto Datadog, Inc.; when the search returns nothing usable, the Actor falls back to an Owler address built from the name or domain. - 🧾 Structured values — numeric
employeesnext to the readableemployeesFormattedand theemployeesRangeband; revenue asrevenueFormattedplusrevenueRange; the address split into street, city, state, country and zip; the CEO as name, title, Owler rating, photo, LinkedIn and Twitter. - 🚦 Misses are visible and free — a profile Owler doesn't have comes back as a row with an
errorfield, which is not charged; turnincludeUnmatchedoff to skip misses instead.
🎬 Quick Start
curl -X POST "https://api.apify.com/v2/acts/foxlabs~company-enrichment/runs?token=YOUR_TOKEN" \-H "Content-Type: application/json" \-d '{"companyNames":["Stripe","Notion","Datadog"],"maxResults":100}'
🚀 Getting Started (3 steps)
- Paste your companies — names, domains or Owler URLs; a domain gives the most exact match.
- Set the cap —
maxResultslimits how many companies are looked up (default 100; 0 = no limit). - Run and export — download the dataset as JSON, CSV, Excel, HTML or XML.
📥 Input
{"companyNames":["Stripe","Notion","Datadog"],"maxResults":100}
| Field | Type | Description |
|---|---|---|
companyNames | array | Company names, one per line. Each is matched through Owler's search suggestions: the first suggestion whose name contains your text (or is contained in it), otherwise Owler's top suggestion. |
companyUrls | array | Owler company URLs (https://www.owler.com/company/<slug>), or a .txt / .csv upload. Used exactly as given; URLs from other sites are ignored. |
companyDomains | array | Domains such as stripe.com. Owler's search is queried with the domain name, and the suggestion whose primary domain equals your domain wins; if none does, the domain is matched like a name. |
maxResults | integer | Most companies looked up in one run (default 100; 0 = no limit). URLs come first, then domains, then names; companies past the cap are skipped. |
maxConcurrency | integer | Profile pages fetched in parallel (default 10; values above 20 are treated as 20). |
includeUnmatched | boolean | On (default): a profile Owler doesn't have comes back as a free row with an error field. Off: it is skipped and only logged. |
proxyConfiguration | object | Apify proxy settings (default: Apify proxy, automatic selection). |
More recipes
- Exact match by domain:
{"companyDomains":["stripe.com"],"maxResults":10}— resolved to Stripe, Inc. in our test run. - Skip misses:
{"companyUrls":[{"url":"https://www.owler.com/company/zzqx-no-such-company-2026"}],"includeUnmatched":false}— the profile Owler doesn't have is only logged. With the default, it comes back as a free row witherror: Empty company in initialState (Owler 404 / Page Not Found).
📤 Output
One row per company. Rows that report a miss carry an error field and no company data: a profile Owler doesn't have (unless includeUnmatched is off), or a page that loaded but could not be read (in any mode). A page that still fails after its retries — blocked or server errors — is only logged, not written. From 25 September 2026 rows with error are not charged.
| Field | Description |
|---|---|
url | Owler profile the row was read from |
name / legalName | Short name and full legal name |
website / domain / logo | Website, root domain, logo image URL |
industry / industries | Owler's industry sectors, comma-joined (e.g. Fintech Software), and its broader industry group (e.g. Banking, Financial Services and Insurance) |
headquarters / address | HQ as city, state, country, and the street address: street1, street2, city, state, country, zipcode |
yearFounded | Founding year |
employees / employeesFormatted / employeesRange | Employee count as a number and as text, and Owler's size band |
revenueFormatted / revenueRange | Revenue figure and band as shown on Owler (e.g. 5.1B, $5B - 10B) |
ownership | Public or Private |
ceo | The executive Owler lists as CEO: name, designation (title), rating (Owler approval rating, 0–100), photoUrl, linkedin, twitter |
description | Owler's one-paragraph company description |
matched | Always true on a company row — misses come back with error instead |
totalCompetitors / totalAcquisitions | How many competitors and acquisitions the source profile lists. The counts are returned; the lists are not (see below) |
competitors / acquisitions / funding | Always empty here — this Actor is scoped to firmographics |
deeperDataAt | Where the full lists come from: the Owler Scraper Actor |
scrapedAt | Timestamp of the lookup |
error | Miss rows only — why the profile could not be read |
Why some fields are deliberately empty. This Actor returns firmographics — the fields you need to enrich a CRM or score a lead list — at a price built for running over a whole list. Competitor lists, funding rounds and acquisitions are a different job: you want them on a handful of accounts, not on ten thousand. So the record carries the counts (so you can see what exists) and points at Owler Scraper, which returns those lists in full along with ticker, phone, leadership and financial history.
In our test run on 2026-09-20 (Stripe, Notion, Datadog, Monzo, Ramp, Kith, Peloton) every company field above was filled on all 7 rows, and totalCompetitors / totalAcquisitions were present on 7/7 — genuinely 0 for Notion and Datadog, whose Owler profiles list no competitors. address.street2 remains partial, as street addresses often have no second line.
Sample — Stripe, from our test run on 2026-09-10:
{"url": "https://www.owler.com/company/stripe","name": "Stripe","legalName": "Stripe, Inc.","website": "https://stripe.com/","domain": "stripe.com","industry": "Fintech Software","industries": ["Banking, Financial Services and Insurance"],"headquarters": "San Francisco, California, USA","address": {"street1": "185 Berry Street","street2": "Suite 550","city": "San Francisco","state": "California","country": "USA","zipcode": "94107"},"yearFounded": 2009,"employees": 8200,"employeesFormatted": "8,200","employeesRange": "5,000 - 10,000","revenueFormatted": "5.1B","revenueRange": "$5B - 10B","ownership": "Private","ceo": {"name": "John Collison","designation": "President","rating": 64,"photoUrl": "https://image4.owler.com/ceo/John_Collison_owler_20240726_224858_original.png","linkedin": "https://www.linkedin.com/in/johnbcollison/","twitter": "https://twitter.com/collision"},"description": "Stripe is a California-based financial infrastructure platform that offers solutions such as payment processing, VAT automation and invoice management for businesses.","logo": "https://image4.owler.com/logo/stripe_owler_20260318_134635_medium.png","matched": true,"totalCompetitors": 23,"competitors": [],"totalAcquisitions": 22,"acquisitions": [],"funding": null,"deeperDataAt": "https://apify.com/foxlabs/owler-intelligence","scrapedAt": "2026-09-20T12:56:21.732Z"}
Stripe's profile lists 23 competitors and 22 acquisitions. This Actor tells you they exist; Owler Scraper returns them.
💼 Use cases
1. CRM enrichment — fill empty account fields. Input: domains from your CRM. Output: industry, HQ, employees, revenue band, ownership. Use: complete account records for routing and reporting.
2. Lead scoring — size and revenue band for every lead.
Input: the company names on a lead list. Output: employees, revenueRange, industry. Use: score and prioritise the list.
3. Account research — a short profile before a call. Input: one company. Output: description, HQ, the CEO with title and LinkedIn. Use: prepare the conversation.
🔗 Integration
JavaScript / Node.js
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: 'YOUR_TOKEN' });const run = await client.actor('foxlabs/company-enrichment').call({"companyNames":["Stripe","Notion","Datadog"],"maxResults":100});const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(items[0]);
Python
from apify_client import ApifyClientclient = ApifyClient('YOUR_TOKEN')run = client.actor('foxlabs/company-enrichment').call(run_input={"companyNames": ["Stripe", "Notion", "Datadog"], "maxResults": 100})for item in client.dataset(run.default_dataset_id).iterate_items():print(item)
Written for apify-client 3 for Python, where call() returns a run object; with version 1 or 2 it returns a dict — write run['defaultDatasetId'] there.
Automation (n8n / Zapier / Make): schedule or webhook → HTTP request to the Actor API with your companyNames or companyDomains → handle the JSON dataset → push to a sheet, CRM or dashboard.
📊 Pricing
Pay-per-event: $0.001 per delivered company record (≈ $1 per 1,000 companies), plus Apify's run-start event ($0.00005 per GB of run memory). Rows that only report a failed lookup (error) are free (since 25 September 2026). A profile Owler doesn't have comes back as such a free row, or produces no row at all with includeUnmatched off. Current pricing.
Spending limit. Before every record the Actor checks the run's maximum charge — the limit you set for the run, or else what is left of your monthly usage limit. When there is no room for another record it stops fetching, keeps what it has delivered, and the status message says how many companies you got.
❓ FAQ
Where does the data come from? From Owler's public company profile pages (owler.com/company/…): the Actor reads the company data embedded in each page. Names and domains are matched with Owler's search suggestions. No login and no Owler account are needed.
Name, domain or URL? A URL is exact. A domain picks the Owler suggestion whose primary domain equals it. A name picks the first suggestion whose name matches your text, otherwise Owler's top suggestion — so check name, legalName and domain in the output. Rows don't repeat your input; match them to your list on those fields.
Are the revenue and employee figures official? They are the figures on the company's Owler profile, passed through unchanged.
Why is matched always true? Every company row is a match. A miss either comes back as a row with error or is left out (see Output).
Can I export to CSV / Excel / JSON? Yes — directly from the Apify dataset.
🐛 Troubleshooting
- A name returns the wrong company — use its domain or paste its Owler URL; names are matched through search.
- A company is missing — look for its row with an
errorfield: Owler has no such profile, or its page could not be read. WithincludeUnmatchedoff, misses are skipped and only the run log lists them. Pages that still fail after their retries are only logged. - Fewer rows than inputs —
maxResults(default 100) caps the lookups, and inputs that resolve to the same profile are fetched once. - The run ended with "stopped because the maximum charge … was reached" — the run's maximum charge, or what is left of your monthly usage limit, covered fewer companies than you asked for. The dataset holds the ones that were delivered; raise the limit and run the rest.
- The run fails with "No companies to enrich" — the input had no names, no domains and no Owler company URLs (URLs from other sites are ignored).
⚖️ Is it legal to scrape this data?
The Actor reads publicly accessible company profile pages. CEO names, photos and social links are personal data under the GDPR and similar laws — process them only with a lawful basis, and check that your use fits the source website's terms. Owler is a trademark of its owner; this Actor is not affiliated with Owler.
🤝 Support & contact
- 🌐 Website: data.foxlabs.com.tr
- 📧 Email: info@foxlabs.com.tr
- 🐛 Issues: open a ticket in the Actor’s Issues tab
- 🧰 More clean B2B data actors: Fox Labs on Apify
Changelog
0.1.20 — 2026-10-08 — README: the Python example works with the current Apify client
- The README's Python example read the results with
run['defaultDatasetId']. With the current Apify client for Python (version 3)call()returns a run object, not a dict, and that line raisedTypeError: 'Run' object is not subscriptable— after the run itself had finished. The example now readsrun.default_dataset_id; with client version 1 or 2, keeprun['defaultDatasetId']. Checked with apify-client 3.2.1, 2.5.1 and 1.12.2. - No code, output field or pricing change.
0.1.19 — 2026-10-07 — the run stops at its maximum charge and says so
- A run that reaches its maximum charge now stops by itself and tells you. The maximum charge is the limit you set for the run, or else what is left of your monthly usage limit. Until now the Actor did not look at it: companies past the limit were logged as enriched but left out of the dataset, with nothing in the run to say so. The Actor now checks the room left before every record, stops fetching when there is none, and finishes as a normal run with a status message that says how many companies were delivered. Nothing past the limit is charged.
- No output field changed, no pricing change.
0.1.17 — 2026-09-26 — misses come back as free rows by default
- Behaviour change:
includeUnmatchedis now on by default. A company Owler doesn't have comes back as a row with anerrorfield instead of being skipped, so a run whose companies all miss no longer ends with an empty dataset and no explanation. These rows are not charged (per-record billing since 25 September 2026). To keep the old behaviour, set"includeUnmatched": false.
0.1.16 — 2026-09-20 — scope made visible in the output (6 new fields, additive)
- Six fields added to every company row.
totalCompetitorsandtotalAcquisitionscarry the counts the source profile lists;competitors,acquisitionsandfundingare returned empty, anddeeperDataAtpoints at Owler Scraper, which returns those lists in full. Previously these fields were absent from the output entirely, so a record looked complete when it was deliberately scoped to firmographics — you could not tell what you were not getting. - Additive change, nothing removed or renamed. Existing integrations keep every field they had; the row goes from 21 to 27 fields. Error rows carry the same six fields so the shape is consistent in both modes.
- Dataset table view now shows the two counts and the pointer, so the scope is visible in the Console as well as in the JSON.
- Measured on a local run of 7 companies (Stripe, Notion, Datadog, Monzo, Ramp, Kith, Peloton): the two counts were present on 7/7 rows and the field count was identical on all 7.
0for Notion and Datadog is the real value — their Owler profiles list no competitors, confirmed against the source. - No pricing change, no change to what is charged: the
company-recordevent and the 25 September switch described in 0.1.15 are unaffected.
0.1.15 — 2026-09-10 — failed lookups become free (per-record billing) + README corrected
- Input descriptions corrected: the cost examples now use the real price ($0.001 per record: 100 ≈ $0.10, 1,000 ≈ $1), and
maxConcurrencysays the Actor caps it at 20. - You will pay only for delivered company records. The Actor now charges a new
company-recordevent for each delivered company, and rows that only report a failed lookup (error) are pushed without a charge (src/billing.js; the record push insrc/main.jsnow goes throughpushRecord, the two error-row pushes stay plain). - Timing: Apify applies pricing changes after a 14-day notice. From 25 September 2026 the pricing switches from the per-dataset-item event to
company-recordat the same price ($0.001). Until then billing is exactly as before; the code detects the switch by itself. - No output field changed.
- README corrected. The 2026-09-07 README documented inputs this Actor does not have (
queries,maxResultsPerQuery,includeRaw) with a placeholder (undefined) example, named the source "public company web and registry sources" (the Actor reads Owler), calledindustrya NACE code andemployeesa registered count, and promised registry-ID lookup, status / legal form / formation date, "formation / status monitoring", "whole dataset in one call", "every row carriesquery", "no degenerate columns" (matchedis alwaystrue) and "empty/failed lookups never billed". The new README describes the real inputs, output and billing, checked on local runs. - The older entries below are kept as written; the 0.0 entry's "registry sources … registry ID" was wrong — the source is Owler, and lookups are by name, domain or Owler URL.
0.1 — 2026-09-07
- Enabled AI-agent payments (x402) + rebuilt the README to the full standard (What-is / when, AI-agents + x402 agentic payments + MCP, Overview, Features, Use cases, Integration, FAQ, Troubleshooting, Support & contact).
0.0
- Initial release: data from public company web and registry sources by name or registry ID.