Company Financials Scraper — Valuation & M&A (Craft.co) avatar

Company Financials Scraper — Valuation & M&A (Craft.co)

Pricing

from $4.00 / 1,000 results

Go to Apify Store
Company Financials Scraper — Valuation & M&A (Craft.co)

Company Financials Scraper — Valuation & M&A (Craft.co)

Scrape company financial intelligence from Craft.co — revenue, income statements, private valuations, market cap, M&A, executives & competitors as clean JSON. Low-cost Crunchbase / PitchBook alternative for VC/PE deal sourcing, M&A research, sales prospecting & CRM enrichment.

Pricing

from $4.00 / 1,000 results

Rating

5.0

(2)

Developer

Berkan Kaplan

Berkan Kaplan

Maintained by Community

Actor stats

2

Bookmarked

27

Total users

4

Monthly active users

4 days ago

Last modified

Share

Company Intelligence — Craft 🏢

foXLabs company-intelligence series: Company enrichment · Owler · Built In · Free lookup

🎉 Turn Craft into clean, structured company intelligence — no login, no API key, one row per company, with firmographics, operating metrics and links. Built for competitive intelligence, procurement and B2B research.

🔍 What is the Company Intelligence — and when should you use it?

Give this actor Craft.co URLs, company names or website domains and it returns each company's Craft.co profile — financials, valuation, executives, M&A and competitors — as clean, deduplicated rows you can filter, export or feed to an AI agent. A name or domain is delivered only after it is verified against the profile (name or website must match). Every run reads the source live.

Use it when you need: a company list for outreach; a quick profile before a call; or a starting point for account research.

Use something else when: you need the official registry filing — this is an intelligence profile, not a government registry.

🤖 Use with AI agents

Already on the Apify MCP server? Ask for this Actor by name: foxlabs/craft-intelligence.

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 record, never for errors.

Otherwise paste this into Claude, ChatGPT, Cursor or any MCP-enabled assistant:

I want to pull company records using the Apify Actor `foxlabs/craft-intelligence`.
Input: `companyNames` (names, website domains or Craft.co slugs), `companyUrls` (exact Craft.co URLs — most precise), `preset` and more — see the Input table below. `maxResults` caps how many results are returned.
Start with: {"companyNames":["Stripe","Airbnb","Notion Labs"],"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/craft-intelligence.md.

📋 Overview

Everything you need to turn Craft company-intelligence profiles into clean, structured data — in one actor, with no login, cookies or API key.

Why teams pick this actor:

  • ✅ One verified profile per company — Craft.co URL, name or website domain in; a name or domain is delivered only when the profile's name or website matches it.
  • 🧹 No empty-promise columns — only fields Craft.co actually fills; degenerate columns are removed.
  • 🔗 Stable identifiers — every row carries its Craft.co URL and slug plus the company website, ready to join across runs and to other Fox Labs actors.
  • 💰 Per-row pricing — a minimal price per delivered row, no subscription.
  • 🤖 Agent-ready — MCP + x402 agentic payments.

✨ Features

  • 🔍 URL, name or domain input — Craft.co URLs in any form (craft.co/stripe, …/stripe/financials); names and website domains are turned into likely Craft.co pages (Craft.co has no public search) and verified by name or website before delivery. Each row says how it was matched (matchedBy).
  • 🏢 Full company profile — revenue and income statements, employee history, valuation / market cap / funding, executives, M&A, competitors, headquarters and offices.
  • 🧹 Clean schema — deduplicated camelCase rows, ready for CSV/Excel/JSON.

🎬 Quick Start

curl -X POST "https://api.apify.com/v2/acts/foxlabs~craft-intelligence/runs?token=YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"companyNames":["Stripe","Airbnb","Notion Labs"],"maxResults":100}'

🚀 Getting Started (3 steps)

  1. Choose your targets — Craft.co URLs (most precise), company names or website domains.
  2. Set the cap — maxResults limits how many results are returned.
  3. Run and export — get a clean dataset as JSON, CSV or Excel.

📥 Input

{"companyNames":["Stripe","Airbnb","Notion Labs"],"maxResults":100}
FieldTypeDescription
presetstringAuto-fills well-known company anchors, then (with Discovery depth > 0) follows Craft.co's competitor graph. NOTE: the graph spans the broader tech/software space…
companyNamesarrayOne company per line: a name (Procter & Gamble), a website domain (stripe.com) or a Craft.co slug (notion-labs). Each becomes likely Craft.co pages; a page is delivered only if its name matches the name, or its website matches the domain. Unmatched entries go to FAILED_PAGES and are never billed.
companyUrlsarrayCraft.co URLs in any form (most precise), company website URLs (treated as domains), or an uploaded .txt/.csv with one company per line (first column; header row skipped).
includeCompetitorsbooleanEach company's competitor list — name, Craft.co URL and revenue (competitor revenue is often null on Craft.co).
includeAcquisitionsbooleanAcquisition / subsidiary history — company, date, amount and Craft.co URL (date & amount are usually null on Craft.co).
includeLeadershipbooleanExecutive team — name + title.
maxResultsintegerHard cap on companies returned (also your cost cap). PPE $4/1K → 100 ≈ $0.40.
maxConcurrencyintegerPages fetched in parallel (1-20). In our test on 2026-10-06 the share of blocked requests was the same at 1, 3, 6 and 8, so this mostly sets the speed.
maxDepthintegerHow far to follow Craft.co's competitor graph for a live, broad pool (not a static anchor list): • 0 = only the companies you list / preset anchors — no…
industryKeywordsarrayOnly applied when depth > 0. Discovered companies whose industry tags match none of these keywords are skipped — this stops drift into unrelated sectors (e.g.…
industryBlocklistarrayOnly applied when depth > 0. Discovered companies whose industry tags match ANY of these keywords are dropped — even if they also match the whitelist. Keeps…
enrichFromOwlerbooleanOFF by default. When ON, companies whose revenue/employees are missing on Craft.co are looked up on Owler.com and backfilled ONLY when Owler's domain matches the…
proxyConfigurationobjectRESIDENTIAL proxy is the default, with exits in the United States unless you pick a country. Craft.co's bot protection answers part of all requests with a challenge (HTTP 403); such a request is retried on another session (up to 10 attempts for a company you asked for, 6 for a discovered competitor). The datacenter proxy was blocked on 23 of 24 requests on 2026-10-06 — keep RESIDENTIAL.

📤 Output

One row per company, saved to the dataset. Every row carries scrapedAt and matchedBy. Inputs that cannot be matched to a Craft.co profile are listed in the run log and in the FAILED_PAGES record of the key-value store — never written to the dataset, so no record is billed for them (from 17 October 2026 a company you asked for that was looked up costs the $0.0005 lookup fee — see Pricing). If nothing at all can be delivered, the run ends as FAILED and its status message lists the inputs. Each FAILED_PAGES entry has a category: not-found (craft.co has no profile at the address(es) tried), blocked (bot protection on every attempt — run again), name-mismatch / domain-mismatch / domain-unverifiable (a profile was found but it is not the company you asked for; a name-mismatch entry with viaRename: true means craft.co redirected the address to a renamed profile), invalid-input, not-reached (the run reached "Maximum companies" first) or error.

FieldDescription
urlUrl
slugSlug
nameName
matchedByHow the row was matched to your input: url, domain (website verified) or name (name verified)
descriptionDescription
websiteWebsite
crunchbaseCrunchbase
foundedYearFounded Year
ownershipOwnership
stockTickerStock Ticker
headquartersHeadquarters
headquartersCityHeadquarters City
headquartersStateHeadquarters State
headquartersCountryHeadquarters Country
employeesRegistered employee count
employeeHistoryEmployee History
revenueRevenue
revenueFormattedRevenue Formatted
revenueExactRevenue Exact
revenueCurrencyRevenue Currency
netIncomeNet Income
financialPeriodFinancial Period
incomeStatementsIncome Statements
valuationValuation
valuationFormattedValuation Formatted
valuationExactValuation Exact
valuationDateValuation Date
isStaleValuationIs Stale Valuation
marketCapMarket Cap
marketCapFormattedMarket Cap Formatted
marketCapExactMarket Cap Exact
marketCapDateMarket Cap Date
sharePriceShare Price
sharePriceDateShare Price Date
totalFundingTotal Funding
totalFundingFormattedTotal Funding Formatted
totalFundingExactTotal Funding Exact
socialSocial
industriesIndustries
industriesTextIndustries Text
acquisitionsAcquisitions
executivesExecutives
competitorsCompetitors
officesOffices

💼 Use cases

1. Competitive intelligence — profile competitors and their metrics. Input: company names. Output: firmographics + metrics. Use: a competitor brief.

2. Supplier research — research suppliers before engaging. Input: company names. Output: company profiles. Use: a vendor shortlist.

3. Account research — brief sales on target accounts. Input: company names. Output: company intelligence. Use: an account one-pager.

🔗 Integration

JavaScript / Node.js

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('foxlabs/craft-intelligence').call({"companyNames":["Stripe","Airbnb","Notion Labs"],"maxResults":100});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items[0]);

Python

from apify_client import ApifyClient
client = ApifyClient('YOUR_TOKEN')
run = client.actor('foxlabs/craft-intelligence').call(run_input={"companyNames":["Stripe","Airbnb","Notion Labs"],"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 input → handle the JSON dataset → push to a sheet, CRM or dashboard.

📊 Pricing

Pay-per-event.

Until 16 October 2026: $0.004 per delivered record; inputs that cannot be matched are not billed. View current pricing.

From 17 October 2026 (15:00 UTC): a delivered company costs the same $0.004, now split into a $0.0005 company-lookup and a $0.0035 record. A company you asked for that we looked up and that certainly resolved to another company (name or website check) costs only the $0.0005 lookup: finding that out takes page requests. A company with no Craft.co profile stays free, and so does a company that stays blocked by Craft.co's bot protection through every retry (that is on our side). A name that craft.co itself redirects to a renamed profile with a different name (viaRename in FAILED_PAGES) is free too — the name you typed was a real address. A profile without a website (unverifiable), lines that are never looked up (not a name, domain or craft.co URL), preset anchors and discovered competitors that fail, and other errors on our side stay free as well. Apify notifies users of the change in advance.

❓ FAQ

Do I need an account, login or API key? No. This reads Craft company-intelligence profiles.

What do I search by? Craft.co URLs (most precise), company names or website domains. There is no fuzzy search: a name or domain is turned into likely Craft.co pages and delivered only if the profile's name or website matches.

How current is the data? Every run queries Craft.co live, so results are as fresh as its profiles.

What does each profile include? Firmographics, operating and company-intelligence attributes and links as published on Craft.

Can I export to CSV / Excel / JSON? Yes — directly from the Apify dataset.

🐛 Troubleshooting

  • Fewer rows than expected — raise maxResults, or refine the input.
  • A name or domain was not delivered (see FAILED_PAGES) — Craft.co has no public search, some companies use a different slug, and renamed companies keep their old slug (Square → Block). Open craft.co, find the company and paste its URL into companyUrls.
  • The row's name is longer than the name you typed — craft.co renamed the profile and redirects the old address to it: OpenAI is delivered as Craft.co's current profile OpenAI Foundation (craft.co/openai-foundation). This happens only when craft.co itself redirects the address and the name you typed leads the new name.
  • Two companies share a name — a name match cannot tell them apart: Notion is a small smart-home company, the well-known one is Notion Labs (craft.co/notion-labs). Use the Craft.co URL or the website domain.
  • The run ended with "No company could be delivered" — the status message says, for each input, whether Craft.co has no profile at the address(es) tried, whether Craft.co's bot protection blocked every attempt, or whether the input resolved to a different company. The run is SUCCEEDED (with no rows) when every failure is the input's; it is FAILED when at least one failure is on our side — a block on every attempt, an error — so run it again. Exact Craft.co URLs avoid the guesswork.
  • A company is listed as blocked in FAILED_PAGES — Craft.co's bot protection answered every attempt with a challenge (10 attempts for a company you asked for). The company may well exist; nothing is billed for it. Run it again.
  • A company is listed as not-found — craft.co redirects that address to its home page, so there is no profile under that slug (Snowflake lives at craft.co/snowflake-computing). Find the company on craft.co and paste its URL.

This actor reads public company-intelligence profiles from Craft. Results can still contain personal data (e.g. a person’s name); personal data is protected by the GDPR and similar laws, so only process it with a legitimate basis. See Apify’s blog post on the legality of web scraping.

🤝 Support & contact

Changelog

0.4.16 — 2026-10-10 — a run that delivers nothing because of its input no longer fails

  • Behaviour change — run status. When nothing could be delivered and every failure is the input's — no Craft.co profile at the address(es) tried, the input resolved to a different company, the profile lists no website, or a line that is not a company at all — the run now ends SUCCEEDED, with the same status message as before ("No company could be delivered — …") and the details in FAILED_PAGES. When at least one failure is on our side — Craft.co's bot protection on every attempt, an error, a requested company the run never reached — the run still ends FAILED, so a real breakage stays visible. Such a run is the user's to fix, not a broken Actor; in the 30 days to 2026-10-10, 8 of the 37 runs by users ended FAILED.
  • Nothing is billed as a result in either case; the lookup fee announced for 17 October 2026 is unchanged. No output field or price changed.

0.4.15 — 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 raised TypeError: 'Run' object is not subscriptable — after the run itself had finished. The example now reads run.default_dataset_id; with client version 1 or 2, keep run['defaultDatasetId']. Checked with apify-client 3.2.1, 2.5.1 and 1.12.2.
  • No code, output field or pricing change.

0.4.14 — 2026-10-06 — fewer blocked pages; "no such profile" told apart from "blocked"

  • Fewer blocked pages. Craft.co's bot protection (Cloudflare) answers part of all requests with a challenge (HTTP 403). Three changes, each measured on 2026-10-06: RESIDENTIAL exits default to the United States when you pick no country; a proxy session that fetched a page is re-used instead of a new one being opened for every request; a company you asked for gets 10 attempts instead of 6 (discovered competitors keep 6). The challenge itself is never solved or bypassed. Local test in the runtime the platform uses (Node 20), old and new code run in the same minutes: the prefill (Stripe, Airbnb, Notion Labs, depth 2) went from 12 and 26 rows with 1 of 3 requested companies to 93 rows with 3 of 3 (three runs); a single-company run failed 3 times out of 6 before and 0 out of 6 after. On the platform the country default alone (0.4.13 with the country set in the input) gave 77 rows and 3 of 3 against 8 rows and 1 of 3.
  • Behaviour change — "no such profile" is certain now and reported on its own. craft.co redirects an address without a company profile to its home page. Until now the redirect was followed and the home page counted as a block, so the address was fetched 6 times and reported as "not found or blocked". It is now recognised on the first answer. FAILED_PAGES entries carry category: "not-found" (no profile at the address(es) tried) or "blocked" (bot protection on every attempt — run again) instead of the single "not-found-or-blocked". Neither is billed — the lookup-fee terms announced for 17 October 2026 are unchanged.
  • Renamed profiles are followed. craft.co/openai now redirects to craft.co/openai-foundation; the row is delivered with the new url and slug. This also works when you ask by name: OpenAI is delivered as Craft.co's current profile "OpenAI Foundation", because craft.co itself redirected the address and the name you typed leads the new name (before, it was reported as "resolved to another company"). A rename to a differently named company (Square → Block) is still not delivered for a name — use the craft.co URL — and such an entry is marked viaRename and will not be charged the lookup fee.
  • Requested companies keep their place under "Maximum companies". Discovered competitors no longer fill the run while a requested company is still being fetched. When the maximum is reached the rest of the queue is not fetched any more. A requested company the run did not get to is listed in FAILED_PAGES (not-reached) instead of being dropped silently.
  • A company that was delivered is not fetched a second time through a competitor link, and no longer shows up in FAILED_PAGES when that second fetch fails.
  • Status message. A finished run now says how many companies were delivered and names the requested ones that were not, with the reason.
  • Presets. openai → openai-foundation, snowflake → snowflake-computing, scale-ai → scale. Removed from the AI / ML preset because craft.co has no profile at these addresses: cohere, midjourney, google-deepmind.
  • Corrected in the README and input descriptions: "Craft.co answers HTTP 403 for unknown company pages" was wrong — it redirects them; the 403 is the bot protection. Concurrency did not change the share of blocked requests in our test (1, 3, 6 and 8), so that advice is gone too.
  • No pricing change and no change to the output fields. A run that delivers nothing still ends as FAILED.

0.4.13 — 2026-10-02 — lookup fee narrowed before it starts: "no profile" stays free

  • The lookup fee announced in 0.4.12 (from 17 October 2026) will not apply when no Craft.co profile is found, or when the profile lists no website: Craft.co answers 403 for unknown pages and for blocked requests alike, and a valid company (craft.co/stripe) stayed blocked through all 6 tries in our test. Charged: delivered companies, and inputs that certainly resolved to another company.

0.4.12 — 2026-10-02 — lookup fee announced for 17 October 2026

  • Pricing change from 17 October 2026 (15:00 UTC): every company looked up costs a $0.0005 company-lookup, and a delivered record drops from $0.004 to $0.0035 — a delivered company costs $0.004 as before. A company you asked for that resolves to another company or has no Craft.co profile costs only the $0.0005 lookup (a valid company that stays blocked after every retry is indistinguishable and is charged the same). Lines never looked up, preset anchors and discovered competitors that fail, and other errors on our side stay free. The code is live now and charges nothing extra until the new price takes effect (src/billing.js).

0.4.11 — 2026-10-02 — Names and domains resolved and verified, every craft.co URL form, file upload, clearer failure message

  • Behaviour change — name inputs are now verified. A name becomes likely Craft.co slugs (legal forms dropped: Stripe Inc → craft.co/stripe; Goldman Sachs Group → goldman-sachs-group, then goldman-sachs; Procter & Gamble → procter-gamble) and a profile is delivered only if its name matches the name you typed (legal-form, group and generic words such as Inc, Holdings or Technologies are ignored). Before, whatever company sat at craft.co/
  • Website domains work. stripe.com or https://www.stripe.com/… → slug candidates, delivered only if the profile's website is on the same domain (craft.co/checkout is a different company at checkout.fi, so checkout.com resolves to craft.co/checkout-com). Before, a domain became craft.co/stripe.com and the run failed. Companies whose Craft.co website is another domain (PayPal → investor.pypl.com, Zoom → zoom.com) do not match by domain — use the Craft.co URL.
  • Every craft.co URL form works: craft.co/x, http://, www., sub-pages (/stripe/financials → the full profile), query strings, trailing slashes. Before, sub-pages returned partial rows and the other forms failed.
  • Uploaded .txt/.csv lists in companyUrls are read (one company per line). Before, the file was ignored and the run failed with "No companies".
  • New field matchedBy (url | domain | name) on every row.
  • Clearer failure message: a run that delivers nothing lists the inputs that were not found or resolved to another company, explains that Craft.co answers HTTP 403 both for unknown pages and for blocked requests, and no longer tells users who already use the RESIDENTIAL proxy to switch to it.
  • Two inputs that resolve to the same company give one row, billed once.
  • README: removed claims of a "relevance-ranked name search", "registry-ID lookup" and "legal form / formation date" fields — this Actor never had them. Prefill and examples use Notion Labs (a bare Notion is a different company). Proxy wording now matches measurements.
  • No pricing change. A run that delivers nothing still ends as FAILED.

0.4.10 — 2026-09-20 — README examples corrected against the real input schema

  • The README's code examples did not match this Actor. They used queries and maxResultsPerQuery — keys that do not exist in this Actor's input schema — with a placeholder value, and the input table listed those same phantom fields. Anyone who copied the AI-agent, cURL, JavaScript or Python example got a failing run. Every example now uses the real schema and matches the Console prefill: {"companyNames":["Stripe","Airbnb","Notion"],"maxResults":100}
  • The input table is regenerated from input_schema.json, so it lists the fields the Actor actually accepts.
  • Removed claims carried over from the same generator template where present: "formation / status monitoring", "a canonical registry record for KYB and due diligence", "every row carries query", and industry described as a NACE code.
  • No code, output field or pricing change.

0.4 — 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.