Blog / Financial statements
Financial statements

How to Convert XBRL Financial Statements to JSON in Python

XBRL tags every number in a 10-K or 10-Q with a taxonomy element. Here is how that structure works and how to pull it into Python as clean JSON.

By the SecFeed teamOctober 15, 20266 min read
Key takeaways

Open the raw XBRL behind any 10-K and you will find thousands of tagged facts, each one wrapped in a taxonomy element name, a context reference and a unit. That structure is exactly why financial data from SEC filings is reliable to compute with, and exactly why reading it by hand is slow. This guide explains how XBRL is put together and how to get it into Python as plain JSON instead.

What XBRL actually is

XBRL stands for eXtensible Business Reporting Language. It is an XML based format that tags each number and disclosure in a financial statement with a standard element name, rather than just placing it in a table for a person to read. A revenue figure is not just a number next to the word "Revenue"; it is tagged as something like us-gaap:Revenues, with a defined context for the fiscal period and entity it applies to.

The SEC has required XBRL tagging of financial statements from public companies since the rule phased in between 2009 and 2011, starting with large accelerated filers and extending to smaller companies afterward.

The building blocks of an XBRL filing

A few pieces repeat throughout every XBRL document:

PieceWhat it defines
Taxonomy elementThe standard tag for a concept, for example us-gaap:Assets or us-gaap:NetIncomeLoss
ContextThe entity (CIK) and period (instant or duration) a fact applies to
UnitThe measurement unit, usually USD, or shares for share counts
FactA single tagged value: an element, tied to a context and a unit

Companies also use extension elements, custom tags defined for a specific filer when no standard US-GAAP element fits. These are less comparable across companies since they are not part of the shared taxonomy, but they still carry real data.

The cover page of a filing, like the entity name and shares outstanding on the filing date, is tagged separately using the DEI (Document and Entity Information) taxonomy rather than US-GAAP.

Inline XBRL

Since the SEC's phased mandate completed in 2021, filers submit inline XBRL (iXBRL), where the tags are embedded directly inside the human readable HTML document instead of a separate XML file. The filing you see in a browser and the tagged data are the same document; the tags are just hidden in the markup.

Inline XBRL does not change what gets tagged, only where the tags live. The taxonomy elements, contexts and units work the same way whether you are reading the standalone XBRL instance or the inline version.

Get this data as clean JSON

SecFeed turns SEC filings into structured data with one API call: GET /v1/xbrl-to-json. 500 free calls a month.

Get a free API key →

Why raw XBRL is hard to work with directly

A single balance sheet line item in raw XBRL is not one clean key and value. It is a fact that references a context ID, which in turn references a period and an entity, plus a unit reference, plus sometimes a dimension for things like segment or subsidiary breakdowns. To reconstruct a readable income statement, you need to:

  1. Parse every fact and its element name.
  2. Resolve each fact's context to get the period it covers.
  3. Group facts by statement and put them back in the order the company actually presented them, since the taxonomy alone does not preserve presentation order.
  4. Handle extension elements that are specific to one filer.

None of this is conceptually hard, but it is enough plumbing that most people doing financial analysis want it done once rather than per filing.

Pulling XBRL as JSON

SecFeed parses a filing's XBRL (or inline XBRL) into statements, keeping the company's own presentation order, plus the cover page facts from the DEI taxonomy. You can look it up by accession number and CIK:

curl "https://secfeedapi.com/v1/xbrl-to-json?accessionNo=0000320193-26-000020&cik=320193&notes=true" \
  -H "Authorization: Bearer YOUR_API_KEY"

The response groups facts into statements, each with its periods and line items:

{
  "cik": "320193",
  "accessionNo": "0000320193-26-000020",
  "statements": [
    {
      "name": "CONSOLIDATED STATEMENTS OF OPERATIONS",
      "periods": ["2026-09-28", "2025-09-29"],
      "lineItems": [
        {"label": "Net sales", "concept": "us-gaap:Revenues", "values": [120000000, 108000000]},
        {"label": "Net income", "concept": "us-gaap:NetIncomeLoss", "values": [18000000, 15500000]}
      ]
    }
  ]
}

In Python, using the stdlib only SDK:

from secfeed import Client

sf = Client("YOUR_API_KEY")
data = sf.xbrl_to_json(accession_no="0000320193-26-000020", cik="320193")
for statement in data["statements"]:
    print(statement["name"])
    for item in statement["lineItems"]:
        print(" ", item["label"], item["values"])

If you want one concept across time instead of a full statement, /v1/xbrl/company-concept returns every historical value for a single taxonomy element for one company, and /v1/xbrl/frames returns one concept across every company that reported it for a given period. /v1/xbrl/company-facts returns everything a company has ever tagged, which is useful for exploring what elements a filer actually uses.

A note on comparing companies

Standard US-GAAP elements make comparison possible, but not automatic. Two companies can report what looks like the same line item under different taxonomy elements, or use a custom extension element instead of the closest standard one. When you build anything that aggregates across companies, check which concept each one actually used rather than assuming the label alone tells you.

Frequently asked questions

What is the difference between XBRL and inline XBRL?

They tag the same underlying data. Plain XBRL is a separate XML instance document. Inline XBRL embeds the tags inside the filing's own HTML, so the document you read and the tagged data are the same file.

Why does my parsed statement have different values than the summary numbers on a financial site?

Different sites may pull different tagged periods, for example a restated prior year versus the originally reported one, or a different level of the statement hierarchy. Always check which context and period a value is tied to.

Do all companies use the same taxonomy elements?

Most use the standard US-GAAP elements for common concepts like revenue and net income, but companies can also define custom extension elements for line items that are specific to their business. Extension elements are not directly comparable across filers.

Is cover page data like shares outstanding part of XBRL too?

Yes, but it uses the DEI (Document and Entity Information) taxonomy rather than US-GAAP, since it describes the filing itself rather than financial results.

Can I get a single financial concept over several years without pulling full statements?

Yes. Querying a single taxonomy element like us-gaap:Assets for one company over time returns that concept's full reported history without needing the rest of the statement.

Get this data as clean JSON

SecFeed turns SEC filings into structured data with one API call: GET /v1/xbrl-to-json. 500 free calls a month.

Get a free API key →

For information only, not investment advice. Data from public SEC filings; verify important figures on SEC.gov. See our AI Disclosure.