COMPANYAI API MCP READY

Owler Company Intelligence API

Most company APIs tell you what a company is. This one also tells you who it competes with, by name, with a follow-on profile link for every rival so a second pass maps the whole market. Alongside that: a numeric revenue estimate and a banded range, employee count and band, total funding, acquisitions, industry, SIC codes, headquarters address, and exchange and ticker for public companies. Pay per company record, MCP-ready for Claude and other agents.

RECORDS2
MEDIAN LAGon demand
FIELDS35

Input parameters

PARAMETERTYPEREQDEFAULTDESCRIPTION
companyUrls string[] yes One or more company profile URLs, for example https://www.owler.com/company/stripe. A bare company slug such as stripe is accepted as shorthand. Up to 1000 per run, collected in chunks of 20. Malformed entries are rejected locally with a warning instead of being sent upstream. Duplicates are removed before collection, so a list with repeats is not billed twice. One charge per company record returned; an input that yields no record is free. — drives your bill

Output schema

FIELDTYPEDESCRIPTIONNULLABLE
result_type string company for a collected record, error for an input that could not be collected. Filter on this before doing anything else. no
companyId string Stable identifier for the company on the source directory. Example: 100441 for Stripe. yes
companyName string Registered or commonly used name, usually with the legal suffix, for example Stripe, Inc. yes
profileUrl string The profile page the record came from. Also present on error rows, so you can tell which input failed. yes
website string The company's own website, including scheme and trailing slash. yes
domain string Bare primary domain. The most reliable join key against a CRM or another dataset. yes
description string One or two sentences of prose on what the company does. yes
industry string First listed industry classification, for example Banking, Financial Services and Insurance. yes
industries string[] Every industry classification on the profile. In practice this is usually a single-element array. yes
founded integer Year founded, as a four-digit number. yes
ownership string Private or Public. Reliable in testing, and the cleanest way to split a list before pulling filings for the public half. yes
status string A source-side label. It came back as NEW for every company tested, including decades-old public ones, so do not read it as an operating status. yes
city string Headquarters city. yes
state string Headquarters state, province or region, spelled out rather than abbreviated. yes
country string Headquarters country code. Not consistently ISO 3166-1 alpha-2: US companies come back as USA while others come back two-letter, so normalise before grouping. yes
zipcode string Headquarters postal code, as a string so leading zeros survive. yes
streetAddress string Headquarters street address. yes
phoneNumber string Main listed phone number. Formatting varies by country and is not normalised. yes
revenue integer Estimated annual revenue in US dollars as a number. An estimate, not a filed figure, and the field to use when you need arithmetic. yes
estimatedAnnualRevenue string The same estimate as a banded range, for example $5B - 10B. The field to use when you need to group or segment. yes
employeeCount integer Estimated headcount as a number. yes
estimatedEmployees string Headcount as a banded range, for example 1,000 - 5,000. Note the thousands separator inside the string. yes
totalFunding integer Total disclosed funding raised, in US dollars. yes
totalAcquisitions integer Number of acquisitions the company has made. yes
totalCompetitors integer The source's own competitor count. It does not equal the length of the competitors array; treat the two as separate figures. yes
competitors object[] The named competitor set. Each entry has a name and a profileUrl you can feed straight back into companyUrls for a second pass. Around 30 names come back per company. yes
ceoName string Chief executive, when the profile lists one. Frequently absent: it was empty on every company tested, so treat it as a bonus rather than a column you can rely on. yes
followers integer How many people follow the company on the source directory. A rough attention proxy, nothing more. yes
exchange string Stock exchange for public companies, for example NYSE. Absent for private companies. yes
ticker string Ticker symbol for public companies. Pairs with exchange as the handoff key into market data. yes
sicCode string[] Standard Industrial Classification codes listed for the company, for example 7372. yes
summary string One-line plain-language recap of the record, so an agent can read a company without post-processing. yes
error_message string On error rows only: why this input produced no company record. yes
error_type string On error rows only: machine-readable category, such as CollectionError or MissingRequiredParameter. yes
fetched_at string UTC ISO-8601 timestamp for the row. Run the same list on a schedule and this turns the dataset into a size and funding history. no

Worked examples

One company — the smallest useful run, and the exact input behind the Owler Company Data API task
{
  "companyUrls": [
    "https://www.owler.com/company/stripe"
  ]
}
Batch, with slug shorthand — a bare slug is accepted, so a spreadsheet column of slugs needs no formatting pass
{
  "companyUrls": [
    "https://www.owler.com/company/figma",
    "salesforce",
    "stripe"
  ]
}
Competitor map, pass two — profileUrl values taken from a first run's competitors array, fed straight back in
{
  "companyUrls": [
    "https://www.owler.com/company/moneytor",
    "https://www.owler.com/company/blockrize",
    "https://www.owler.com/company/duespayment",
    "https://www.owler.com/company/bondaval"
  ]
}
Public companies only — exchange and ticker populate here and stay empty for private firms, so this is the handoff into market data
{
  "companyUrls": [
    "https://www.owler.com/company/salesforce",
    "https://www.owler.com/company/figma"
  ]
}
Monthly watch list — save this as a task, attach a monthly schedule, and fetched_at turns the dataset into a headcount history
{
  "companyUrls": [
    "https://www.owler.com/company/stripe",
    "https://www.owler.com/company/adyen",
    "https://www.owler.com/company/gocardless"
  ]
}
POWER-USER TIP
Map a market in two passes, not one — Run one seed company, collect the profileUrl of every entry in its competitors array, dedupe that list, and run it back through companyUrls. Pass two is where the map actually appears. Budget for it first: roughly 30 names come back per company, so one seed costs about 30 charged records on the second pass.
POWER-USER TIP
totalCompetitors and the competitors array disagree, and that is expected — Stripe returned totalCompetitors of 23 alongside 30 named entries. The count is the source's own figure and the array has its own ceiling. Use the array when you need names, use the count only as a rough signal, and never assert one from the other.
POWER-USER TIP
The competitor set is sharpest on mid-market companies — For a household name the returned set mixes real rivals with small, loosely related firms: Stripe's list included Morgan Stanley next to several companies nobody would call a payments competitor. On mid-market and niche companies it is far tighter. Eyeball the first run before you build a pipeline on it.
POWER-USER TIP
Only company rows cost money — One charge fires per row with result_type of company. Error rows, rejected URLs and empty runs cost nothing, so a list with dead profiles in it is safe to submit. A slug that does not exist comes back as an error row reading "The data service could not return a record for this company." rather than vanishing from the output. The run also reads its own budget cap first and collects only what it can pay for, rather than fetching records it would have to discard.
POWER-USER TIP
Two numbers for revenue, and they are for different jobs — revenue is an integer you can sum and sort; estimatedAnnualRevenue is a band you can group by. Both are estimates rather than filed figures, which is the whole point for private companies, so present them as ranges when the number reaches a customer.
POWER-USER TIP
Read the dataset through its saved views — Append ?view=overview to the dataset items URL for the firmographics table, or ?view=competitors for company, competitor count and the named set. Neither needs a transformation written by hand, and both export to CSV or Excel.
POWER-USER TIP
Join on domain, not on name — companyName carries legal suffixes that vary by record, for example Stripe, Inc. and Figma, Inc. The domain field is the bare host and is the field to match against a CRM.
POWER-USER TIP
The per-record price falls with your platform tier — $0.006 on the free tier, $0.0057 at bronze, $0.005415 at silver, and $0.005144 at gold and above. A 1,000-company run therefore lands between $5.14 and $6.00.

Coverage

35
fields per company row — including error fields
1,000
companies per run — hard cap, raised per account on request
30
competitor names per company — observed ceiling on the array
20
companies per collection chunk — pushed and charged before the next chunk
2
saved dataset views — overview and competitors
7
published example tasks — each one a saved, runnable input

Tasks

Saved runs with the inputs already filled in — each one a standalone page and a working configuration example.

Request a task →

Written about this source

Walkthroughs, worked examples and posts about this source.

Code

curl

curl -X POST "https://api.apify.com/v2/acts/johnvc~owler-company-api/run-sync-get-dataset-items" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"companyUrls": ["https://www.owler.com/company/stripe"]}'

Python

from apify_client import ApifyClient

client = ApifyClient("APIFY_TOKEN")
run = client.actor("johnvc/owler-company-api").call(
    run_input={"companyUrls": ["https://www.owler.com/company/stripe"]}
)
for item in client.dataset(run.default_dataset_id).iterate_items():
    if item.get("result_type") != "company":
        continue
    print(item["companyName"], item.get("estimatedAnnualRevenue"),
          item.get("employeeCount"), item.get("totalCompetitors"))

Python - competitor map in two passes

from apify_client import ApifyClient

client = ApifyClient("APIFY_TOKEN")
actor = client.actor("johnvc/owler-company-api")

seed = actor.call(run_input={"companyUrls": ["https://www.owler.com/company/stripe"]})
rivals = []
for item in client.dataset(seed.default_dataset_id).iterate_items():
    for c in item.get("competitors") or []:
        rivals.append(c["profileUrl"])

rivals = list(dict.fromkeys(rivals))          # dedupe, keep order
print(f"pass two will charge for up to {len(rivals)} records")

mapped = actor.call(run_input={"companyUrls": rivals})
for item in client.dataset(mapped.default_dataset_id).iterate_items():
    if item.get("result_type") == "company":
        print(item["companyName"], item.get("domain"), item.get("estimatedEmployees"))

MCP - add to Claude Code

claude mcp add --transport http owler \
  "https://mcp.apify.com/?tools=actors,docs,johnvc/owler-company-api"

Changelog

2026-08-08 0.0.8 Rebuilt after a platform-wide dataset type fix; the MCP tool call was re-verified against the hosted server.
2026-08-07 Published on the Apify Store with seven example tasks.
2026-08-05 Pay-per-event pricing set at $0.0057 per company record, with the standard tier ladder down to $0.005144.

What people use it for

Alternatives

Crunchbase Company API — better when you need the funding rounds and the investors behind them, round by roundours PitchBook Company API — private-market financials, valuation and deal history on the same accountsours LinkedIn Company API — a second, independent read on headcount when the estimate mattersours Startup Investor Database — use this instead when the question is who funds a segment rather than who competes in itours
Owler's own subscription product — genuinely better if you want curated alerts, a news feed and analyst-maintained competitor lists rather than raw rowscompeting
Older Owler scrapers on the same marketplace — cheaper on paper, but no documented field list and a visibly lower run success rate on their store cardscompeting