Financials Normalizer avatar

Financials Normalizer

Pricing

from $10.00 / 1,000 us company-period results

Go to Apify Store
Financials Normalizer

Financials Normalizer

Standardises company financial statements from official filings (SEC XBRL and Companies House UK), with growth metrics, earnings-quality flags, and revenue-by-segment breakdowns -- every number linked back to its source filing.

Pricing

from $10.00 / 1,000 us company-period results

Rating

0.0

(0)

Developer

Elliot Rose

Elliot Rose

Maintained by Community

Actor stats

1

Bookmarked

2

Total users

1

Monthly active users

6 days ago

Last modified

Categories

Share

Standardises company financial statements from official filings — SEC XBRL (US) and Companies House iXBRL (UK) — into one consistent schema of ~30 line items and 8 ratios per company-period, plus growth metrics, plain-language earnings-quality flags, and (opt-in) revenue-by-segment breakdowns. Every number links back to the exact filing (accession, form, filed date, and a direct URL) it came from.

Give it tickers or CIKs (US) or company numbers (UK); it resolves them, pulls the filer's full fact history, and normalises the mess of inconsistent tagging (Revenues vs SalesRevenueNet vs RevenueFromContractWithCustomerExcludingAssessedTax; UK TurnoverRevenue vs Turnover) into one shape you can chart or diff across companies — US or UK, side by side.

Why this is different from a cheap fundamentals API

It's point-in-time correct, not just "latest number." Every US row separates standardized (the latest-filed value for that period, restatements included) from original (what was first reported, before any restatement) — and this is the one thing most low-cost fundamentals APIs get wrong or don't offer at all. Feed it a pointInTime date and it reproduces exactly what was knowable as of that date: later restatements become invisible, periods not yet filed come back null. That's the difference between a backtest with lookahead bias baked in and one without. If you're building a screener, backtester, or anything that scores historical decisions against financial data, this is the feature that matters most here.

Getting this genuinely right took real work: SEC's own fy field on an XBRL fact reflects which filing it was extracted from, not which real fiscal year the period belongs to (every 10-K reports ~3 years of comparative figures, and all of them get tagged with the current filing's year). Naively trusting it — which is what most quick XBRL parsers do — silently merges different fiscal years together. This Actor buckets by the fact's real calendar period instead, verified against real multi-year filing histories across several large-cap filers.

Input

FieldTypeNotes
tickersstring[]e.g. ["AAPL", "MSFT"]
ciksstring[]with or without leading zeros / CIK prefix
ukCompanyNumbersstring[]UK companies via Companies House — see UK support below
statementsenum[]IS, BS, CF; default all three
periodsenumannual (default), quarterly, ttm
yearsintegerfiscal years of history, default 5, max 20
pointInTimedate stringonly consider filings filed on/before this date — see "point-in-time correct" above
includeRawTagsbooleanadd a raw_facts_sample field per row
includeSegmentsbooleanadd a segments field per US row with a revenue-by-product/geography breakdown, when the filer reports one. Costs 1-2 extra requests per filing — off by default.
secUserAgentstringrequired for US"Your Company Name contact@example.com", per SEC's fair access policy
companiesHouseApiKeystring (secret)required for UK — get one free at developer.company-information.service.gov.uk
maxConcurrencyintegercompanies processed in parallel, default 3

At least one of tickers, ciks, ukCompanyNumbers is required.

Output

One dataset row per company-period (US) or per company (UK — Companies House gives one "latest accounts" snapshot, not a queryable multi-year history the way SEC does). Example (US, periods: "annual"):

{
"cik": "0001234567",
"ticker": "ACME",
"entity_name": "ACME CORP",
"market": "us",
"fy": 2022,
"fp": "FY",
"period_start": "2022-01-01",
"period_end": "2022-12-31",
"form": "10-K",
"filed_at": "2023-02-15",
"accn": "0001234567-23-000010",
"filing_url": "https://www.sec.gov/Archives/edgar/data/1234567/000123456723000010/",
"standardized": {
"revenue": 1050000,
"cost_of_revenue": 600000,
"gross_profit": 450000,
"operating_income": 350000,
"net_income": 300000,
"eps_basic": 3.0,
"eps_diluted": 2.9,
"total_assets": 5500000,
"current_assets": 2200000,
"cash": 1100000,
"total_liabilities": 2300000,
"current_liabilities": 850000,
"long_term_debt": 1400000,
"equity": 3200000,
"operating_cash_flow": 400000,
"capex": 120000,
"free_cash_flow": 280000,
"shares_outstanding": 105000
},
"original": {
"revenue": 1000000
},
"ratios": {
"gross_margin": 0.4286,
"operating_margin": 0.3333,
"net_margin": 0.2857,
"current_ratio": 2.5882,
"debt_to_equity": 0.4375,
"roe": 0.09375,
"roa": 0.05455,
"fcf_margin": 0.2667
},
"growth": {
"revenue_yoy": 0.3125,
"net_income_yoy": 0.2,
"revenue_cagr_2y": 0.2749
},
"red_flags": [
{
"flag": "restated",
"severity": "info",
"detail": "This period's figures were revised in a later filing: revenue. `standardized` shows the latest-filed value; `original` shows what was first reported."
}
],
"raw_tag_map": {
"revenue": "Revenues",
"cost_of_revenue": "CostOfRevenue",
"total_liabilities": "Liabilities"
},
"missing_fields": ["interest_expense", "r_and_d", "sga", "..."],
"confidence": 1.0,
"confidence_note": "All requested line items were found for this period.",
"derived_items": ["gross_profit", "free_cash_flow"],
"derived": false,
"segments": []
}

Notes on the shape:

  • standardized always uses the value from the latest-filed accession ("restated view"). original carries only items where the earliest-filed accession reported a different value — i.e. it only appears for items that were actually restated. In the example above, revenue was originally reported as 1,000,000 and later restated to 1,050,000 in a subsequent 10-K's comparative column.
  • growth — YoY (annual and quarterly), QoQ (quarterly), and CAGR (annual, spanning the actual window returned) for revenue, gross profit, operating income, net income, and free cash flow. TTM rows get a real TTM-vs-year-ago-TTM YoY when 8 quarters of history are available. The first row in any series has nothing to compare against (growth: {}); a gap in fiscal-year coverage is detected and skipped rather than silently computing a multi-year change and calling it YoY.
  • red_flags — plain rule-based earnings-quality checks, no AI/LLM involved: restatement detection (now reliable — see the point-in-time note above), receivables growing much faster than revenue (possible aggressive revenue recognition), profit not converting to operating cash flow, and sharp leverage (debt/equity) increases. Every flag names the exact numbers behind it and is worth a second look, not a verdict. An empty list means "checked, nothing found" — it's always present, never a missing key.
  • confidence_note — a plain-language explanation of the confidence score: whether missing items are a real data gap (core financials absent) or just secondary items this filer doesn't separately disclose (common — most filers don't break out goodwill from intangibles). Purely algorithmic, no AI involved, same as everything else in this Actor.
  • segments (only present when includeSegments: true) — revenue by product/segment/geography, parsed from the filing's own disaggregation note when it reports one. [] is an honest, valid result for single-segment filers, not a failure. Labels (member_label) are best-effort formatting of the raw XBRL member name; the member/axis fields are the authoritative, unambiguous values.
  • raw_tag_map shows which XBRL tag was actually used for each item that has a value, so you can audit exactly where a number came from.
  • missing_fields lists standardised items with no value for this period (no matching tag, or excluded by pointInTime).
  • derived_items lists items computed from others rather than read directly from a tag (e.g. gross_profit = revenue - cost_of_revenue when no GrossProfit tag exists; free_cash_flow = operating_cash_flow - capex, always derived; total_liabilities = total_assets - equity when Liabilities isn't tagged).
  • fp: "Q4" rows (in periods: "quarterly") and fp: "TTM" rows are computed, never filed directly — flow items are derived: true; instant (balance-sheet) items are simply the fiscal-year-end (or latest-quarter-end) values, since a balance sheet has no "Q4-only" figure.
  • pointInTime reproduces what was knowable as of a given date: only filings filed <= pointInTime are considered, so later restatements are invisible and periods not yet filed come back with null values and confidence: 0.

A company that resolves but has no XBRL facts on file produces one row: {"cik": ..., "identifier": ..., "market": "us", "error": "no XBRL facts on file for this filer (pre-2009 filer or non-reporting entity)"} — every failure path returns a specific, honest reason, never a silent blank.

UK output shape

UK rows use the same standardized/ratios/confidence/confidence_note shape (so a UK and a US row are directly comparable field-by-field), but have market: "uk", company_number instead of cik/ticker, no fy/fp (Companies House gives one latest-accounts snapshot per call, not a queryable history), and an extra.employees field UK filers commonly disclose that US filers don't. growth/red_flags are empty ({}/[]) for UK rows today — no historical series to compare against yet.

Be aware of a real, structural UK data limitation (documented, not hidden): unlike SEC filings, UK company accounts aren't uniformly structured data. Micro-entity and abbreviated accounts are legally allowed to omit the profit & loss account entirely, so revenue/net_income will genuinely be unavailable for many small UK private companies — confidence_note explains this per row. Some older/small filings are plain PDF scans with no machine-readable data at all — that produces a clear error row ("...no machine-readable (iXBRL) version available..."), never a silent gap. This module targets the common FRS-102/UK-GAAP small-company taxonomy; full IFRS support for large UK-listed groups is out of scope for now.

Pricing events

EventPriceWhen
company-period-us$0.01each standardised US (SEC) company-period row pushed
company-period-uk$0.02each standardised UK (Companies House) company-period row pushed
no-data$0.002a requested company/CIK/UK number resolved but produced no rows

MCP tools

This Actor is designed to back two MCP tools for downstream agents:

  • get_financials(ticker, period) — run with tickers: [ticker], periods: period (annual/quarterly/ttm), return the standardised rows.
  • compare(tickers, metric) — run with tickers, then project standardized.<metric> (or ratios.<metric>, or growth.<metric>_yoy) across companies and periods for a side-by-side comparison.

Provenance promise

Every number in standardized and original traces back to a specific filing: the row's accn + form + filed_at identify the exact filing, filing_url links straight to it, and raw_tag_map names the exact tag (US). Nothing is estimated from outside sources — items with no matching tag are null and listed in missing_fields, not guessed. The only computed values are the ones in derived_items (simple, documented arithmetic), growth (documented formulas), and red_flags (plain rule-based checks) — never third-party data, never an LLM guess.

Limitations

  • Banks, insurers, and other regulated-industry filers commonly use different XBRL tags for analogous concepts (e.g. InterestAndDividendIncomeOperating instead of Revenues, Deposits-heavy balance sheets) that this actor's TAG_MAP does not specifically target — expect lower confidence and more missing_fields for these filers.
  • Pre-2009 filers / periods have no XBRL data on data.sec.gov at all (XBRL mandates phased in 2009–2011); these return a no-data row.
  • UK micro-entity/abbreviated accounts can legally omit the P&L entirely, and some filings are PDF-only with no machine-readable data — see "UK output shape" above. Full IFRS-taxonomy support for large UK-listed groups is not yet built.
  • segments only covers revenue-by-product/geography (the common ASC 606 disaggregation note); segment-level profit/assets (a different note) aren't extracted. Table layouts vary by filer — a genuinely different shape than the common case produces [], not a guess.
  • Fiscal-quarter Q4 and TTM figures for flow items are derived by subtraction, not filed directly by the company; they inherit any inconsistency in the underlying quarterly/annual tags (e.g. a mid-year accounting change can make a derived Q4 look odd).
  • confidence is the share of core line items present after derivation — it is a completeness signal, not an accuracy guarantee. confidence_note explains what's actually missing and why.
  • red_flags are heuristic signals worth a human second look, not findings — thresholds are tuned to avoid noise (e.g. a leverage-ratio flag requires both a meaningful relative and absolute change, so a near-zero-debt company moving from "almost none" to "still almost none" doesn't trigger a false alarm) but are not a substitute for real diligence.