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.
- Every US public company's 10-K and 10-Q financial statements are tagged in XBRL, a structured format built for machines, not for reading in a browser.
- Each fact is tied to a taxonomy element, a context defining the period and entity, and a unit, which is why raw XBRL is verbose.
- Inline XBRL (iXBRL) embeds those same tags inside the human readable filing document itself.
- You can skip parsing the taxonomy and contexts yourself and pull every statement as ordered JSON instead.
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:
| Piece | What it defines |
|---|---|
| Taxonomy element | The standard tag for a concept, for example us-gaap:Assets or us-gaap:NetIncomeLoss |
| Context | The entity (CIK) and period (instant or duration) a fact applies to |
| Unit | The measurement unit, usually USD, or shares for share counts |
| Fact | A 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.
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.
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:
- Parse every fact and its element name.
- Resolve each fact's context to get the period it covers.
- 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.
- 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¬es=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.
For information only, not investment advice. Data from public SEC filings; verify important figures on SEC.gov. See our AI Disclosure.