Company Firmographics Scraper - Revenue, Headcount, HQ avatar

Company Firmographics Scraper - Revenue, Headcount, HQ

Pricing

from $0.92 / 1,000 company returneds

Go to Apify Store
Company Firmographics Scraper - Revenue, Headcount, HQ

Company Firmographics Scraper - Revenue, Headcount, HQ

Turn a company domain or name into one clean row: legal name, website, street address, industry sectors, exact employee count, exact revenue, founding year, ownership and ticker. No key, no login, no browser. A lookup that cannot be confirmed is flagged free, never billed as your answer.

Pricing

from $0.92 / 1,000 company returneds

Rating

0.0

(0)

Developer

Dami's Studio

Dami's Studio

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

a day ago

Last modified

Categories

Share

Company Firmographics Scraper - Revenue, Headcount and HQ from a Domain

Give it a domain, a company name or an Owler profile link. Get one row back with the legal entity name, the website, the full street address, the industry sectors, the exact employee count, the exact revenue in dollars, the founding year, the ownership, the status, and the ticker and exchange if it is listed. No account, no API key, no login, no browser.

  • Employee count and revenue come back as exact integers: 7,600 staff and $13,269,000,000, not "1,001-5,000" and "$10B+".
  • The full postal address, down to the street line and the postcode.
  • A company that has been bought reports status: "Acquired" and names the parent and the month.
  • Every row is checked against the company you asked for. A profile that does not match is handed over as a free note saying what it found instead, never billed as your answer.
  • Run it with empty input and you get a labelled sample row, free, so you can see the shape first.

What this does not do

Read this part first, because it is where the surprises are.

  • About one lookup in ten comes back without a company, and that is the honest number. Measured on 50 real domain lookups through this Actor: 45 returned a company, 5 did not. All five misses were the same shape: a profile exists, but it is filed under a different website than the one asked for, so it was refused rather than guessed at. You are not charged for a miss. The note you get instead names the profile that was found, so you can pass its link straight back and take it deliberately. Well-known companies land more often than long-tail ones: 24 of 25 on the first batch, 21 of 25 on a deliberately obscure second batch.
  • A name on its own is a weaker question than a domain, and it is the one place a wrong company can still get through. Plenty of firms share a name. A name-only lookup is returned when the name on the profile matches yours once the legal suffix is stripped, but nothing then confirms it is your company rather than a namesake. Those rows carry matchedOn: "name" so you can see which ones rest on that. If you have the domain, use the domain: a domain lookup is only returned when the website on the profile is that exact domain, so it cannot hand you a namesake.
  • Revenue is an estimate, not a filing. For public companies it tracks reported figures closely. For private ones it is the source's own model. Treat it as a size band that happens to be written as a precise number, and do not put it in an audit.
  • Blanks are the source's blanks. Small and very new companies often have a profile with almost nothing on it. profileCompleteness is the source's own 0-100 fill rate for that record: 100 is a full profile, 25 is a stub with a name and a city. Null means not published. It does not mean zero. A company with no published revenue returns revenueUsd: null, never 0.
  • No people. The underlying profile carries named executives with photographs and their LinkedIn URLs, plus a switchboard number. None of that is emitted. This returns facts about companies.
  • No funding rounds, no investors, no news, no competitors, no employee reviews. One company, one row of firmographics.
  • Country codes are not normalised. The source writes CA, GB and USA on the same field and they are published exactly as found rather than converted into a standard that might be wrong. If you need ISO-2 everywhere, map USA yourself. It is the only three-letter code seen so far.
  • It does not find companies for you. This is enrichment, not discovery: you bring a list, it fills in the columns. There is no "give me every fintech in Berlin" search.

Input

{
"companyDomains": ["stripe.com", "deliveroo.co.uk", "octopus.energy"],
"maxResults": 25
}
FieldWhat it does
companyDomainsThe company's own website domain. The most reliable way to ask, because the returned profile is checked against it. Scheme and www. are stripped for you.
companyNamesCompany names. Looser than a domain; see the note above. If you supply names and domains as two lists of the same length, they are paired up and each pair counts as one company rather than two.
companyUrlsLinks of the form https://www.owler.com/company/shopify. Taken at face value and always returned if the page exists, so this is the fix for a lookup that came back unsure.
maxResultsCeiling on companies returned, whatever the lists hold. Hard limit 1,000. Keep it low while testing, because you pay per company returned.
proxyUrlsLeave empty. The run brings its own addresses. Fill it in only if you want the traffic to leave through servers you already pay for, as http://user:pass@host:port.

Output

One row per company. A real row from a real run:

{
"ok": true,
"charged": true,
"recordType": "company",
"companyName": "Shopify, Inc.",
"shortName": "Shopify",
"website": "https://www.shopify.com/",
"domain": "shopify.com",
"description": "Shopify is a Canada-based multinational company that provides E-commerce solutions for online retailers.",
"industrySectors": ["E-commerce"],
"industryGroups": ["Software, Internet & Computer Services"],
"employeeCount": 7600,
"revenueUsd": 13269000000,
"foundedYear": 2004,
"ownership": "Public",
"status": "Independent Company",
"parentCompany": null,
"acquiredOn": null,
"ticker": "SHOP",
"exchange": "NYSE",
"street1": "151 O'Connor Street",
"street2": "Ground Floor",
"city": "Ottawa",
"state": "Ontario",
"country": "CA",
"postcode": "K2P 2L8",
"owlerUrl": "https://www.owler.com/company/shopify",
"companyId": "100740",
"profileCompleteness": 100,
"matchedOn": "domain",
"requestedName": null,
"requestedDomain": "shopify.com"
}

Field notes

  • companyName is the legal entity, which is often not the brand. Airtable comes back as Formagrid, Inc. and Instacart as Maplebear, Inc. shortName is the brand if that is what you wanted.
  • employeeCount and revenueUsd are exact integers or null. Null means the source has not published a figure. It is never written as 0.
  • status is the company's standing: Independent Company, or Acquired. When it is Acquired, parentCompany names the buyer and acquiredOn gives the month, e.g. Deliveroo PLC reports Acquired / DoorDash, Inc. / 05/2025.
  • ticker and exchange are filled only for listed companies. A private company returns null for both, and ownership says Private.
  • industrySectors is the specific sector, such as E-commerce. industryGroups is the broad bucket above it, such as Software, Internet & Computer Services. Thin profiles often have the group and not the sector.
  • matchedOn says which evidence returned this row: domain means the website on the profile is exactly the domain you gave, and is the strongest; name is a name-only lookup, where the name is the only evidence there was; url means you supplied the link yourself. If you only want the strongest, filter on matchedOn == "domain".
  • profileCompleteness is the source's own 0-100 fill rate. Sort by it descending and the thin records fall to the bottom.
  • requestedName and requestedDomain echo what you asked for, so you can join the output back onto your input list without matching on names.

What it costs

$0.92 per 1,000 companies returned, plus a $0.0002 start fee per run. Flat on every plan, with no volume tiers, no minimum, no subscription.

You are charged only for companies that come back with data. About one lookup in ten cannot be resolved to a profile, and those return an uncharged row telling you so. On a list of 1,000 domains you would expect roughly 900 rows and a bill near $0.83, not $0.92.

Nothing else bills. A run that reaches nothing is free past the start fee, a domain that resolves to no profile is free, and a row dropped because the profile's website did not match the domain you asked for is free. That last one is deliberate, and it is why a lookup occasionally returns nothing rather than returning a company with a similar name.

How it works

It reads the company's public profile page and pulls the structured record the page is built from, rather than scraping rendered text. That is why the numbers are exact integers instead of parsed strings, and why a field that is genuinely empty comes back null rather than as a guess.

The site refuses a share of requests outright. Six different connection profiles were measured against it from the cloud, and they were not close: the one this Actor reaches for first answered 42 out of 42, while the profile most scrapers reach for by habit managed 11 out of 45 in the same job against the same addresses. When a request is refused the run changes both its connection profile and its outbound address and asks again, up to six times, and a refusal that survives all six is reported as a free note rather than billed.

Turning a domain into the right profile is the other half. The address is derived from the domain and the record that comes back is then checked against what you asked for, because a plausible-looking address can be a real page belonging to a different company with a similar name. That check is the reason a small number of lookups return nothing: refusing is the right answer when the alternative is billing you for somebody else's headcount.

What people use it for

  • Filling in the size, revenue and location columns on a CRM export that arrived as nothing but company names and domains.
  • Scoring inbound sign-ups by company size before a human looks at them.
  • Territory and account planning, where a real headcount matters more than a band.
  • Checking whether a supplier or counterparty still exists independently, since an acquired company reports its parent.
  • Building a market map from a list of domains you already have.

Reading the output

Every run writes three kinds of row and they are easy to tell apart:

  • Real rows carry "charged": true and "recordType": "company". One billed event each.
  • The sample row carries "_sample": true, "charged": false and "recordType": "sample". There is exactly one, it only appears when the input had no company in it, and it exists so you can see the shape before you spend anything.
  • Notes carry "_diagnostic": true, "charged": false and an errorCode worth switching on: NO_RESULTS when a profile was found but did not match the company you asked for (the message names what it found), NOT_FOUND when no profile exists at all, BLOCKED when the source refused every attempt, BAD_INPUT when an entry could not be turned into a lookup, TIME_BUDGET when the run ran out of time before reaching an entry.

The difference between NO_RESULTS and BLOCKED is the one that matters: the first means the company genuinely could not be confirmed, the second means nobody got to look and a re-run will usually succeed. Neither is charged.

If you only want data, filter on charged == true. The count of those rows is the number of events you were billed for, so the dataset is its own invoice.

Limitations

  • Coverage is good for established businesses and thin for very small, very new or privately held local companies. A profile may exist with only a name, a city and a founding year.
  • Revenue and employee figures are the source's estimates. They are refreshed periodically, not live, and a company that grew this quarter may still read last quarter's headcount.
  • A company with no profile returns an uncharged note. There is no fallback to another source.
  • Name-only lookups are refused unless the name matches exactly after the legal suffix is stripped, so a common or abbreviated name may come back unmatched even though the company is covered.
  • The source writes country codes inconsistently (CA, GB, USA) and they are published as found.
  • Executives, phone numbers, funding rounds, investors, acquisitions made, competitor lists and news are all present on the source record and all deliberately not emitted.
  • The hard ceiling is 1,000 companies per run. Split bigger lists across runs.
  • A share of requests is refused by the source at random. The run retries across several connection profiles and addresses, and reports the ones that never got through without charging for them.

Questions

Do I need an account or an API key for anything? No. There is no login, no cookie and no key anywhere in this Actor, and you do not need an account with the source.

Why is revenue null on a company I know makes money? Because the source has not published a figure for it, which is common for private companies. Null means "not published". It is never written as 0, so you can tell a genuine blank from a genuine zero.

I asked for a domain and got a note saying it was not confident. What now? That means a profile was found whose website is a different domain from the one you gave. The note names it. If it is the company you meant, put its owler.com/company/... link in companyUrls and it will be returned. If it is not, you have been saved from a wrong row.

Can I look up a company by name only? Yes, but it is the weakest of the three inputs and it is deliberately strict. Supplying the name and the domain together as two lists of the same length is better than either alone.

Is the employee count exact or a band? An exact integer, when the source publishes one. That is the main reason to use this rather than a profile scraper that returns "1,001-5,000 employees".

What happens on a company that has been acquired? status reads Acquired, parentCompany names the buyer and acquiredOn gives the month. The rest of the row still describes the company you asked about, not the parent.

Will the run fail if the source is down? No. You get uncharged notes saying what could not be reached, and the run still finishes as succeeded. A failed run would still bill the start fee, which would mean paying to be told something was broken.

Can I run this on a schedule? Yes. Nothing is held between runs, and requestedDomain gives you a stable key to join today's rows onto yesterday's.