SEC XBRL in Python

SEC XBRL API Python: company facts, frames and submissions

The SEC publishes structured XBRL data as free JSON: companyfacts, frames and submissions. This SEC XBRL API Python guide covers the three endpoints, the required User-Agent header, fair-access guidance, and why point-in-time facts matter for backtests.

Get a free API key See pricing Download free samples

What the SEC XBRL API is

Every filing on EDGAR carries structured financial data tagged in XBRL. The SEC exposes that data through free JSON endpoints, and for Python users they are the cheapest source of raw fundamentals available. There is no key and no charge; the only obligations are a User-Agent header and fair-access behavior.

Three endpoints do most of the work in any SEC XBRL API Python workflow. companyfacts returns every reported fact for one company. frames returns one concept across all companies for one period. submissions returns the filing index for one company, including accession numbers and filing dates.

companyfacts, frames and submissions

companyfacts is the workhorse: one request returns all units and all periods the company has ever tagged, grouped by taxonomy such as us-gaap, ifrs-full and dei. It is large — tens of megabytes for a long-lived filer — so fetch it once and store it locally.

frames answers cross-sectional questions: give it a concept, a period and a year, and it returns that value for every filer, which is useful for screens and sector medians. submissions is the metadata spine: it tells you what was filed, when, and under which accession number, which is how you link facts back to documents.

The User-Agent header and fair access

Every request must identify you. The SEC asks for a User-Agent header in the form of a company name plus a contact email, and its fair-access guidance caps automated traffic at 10 requests per second. That is generous for a nightly job and tight for a mass scrape, so pace your loop and cache aggressively.

Respect the guidance and the endpoints stay available: identify honestly, stay under the ceiling, and never re-download companyfacts you already have. When you need faster bulk access across the whole universe, that is the point at which a vendor API earns its fee.

Filed dates, restatements and point-in-time

Every XBRL fact carries more than a value: it carries the period it describes and the filing that reported it. The same concept can appear in several filings with different values — a preliminary 8-K figure, the 10-Q figure, then a restated 10-K figure. All of them are true; they were just known at different times.

That is why point-in-time matters. Any SEC XBRL API Python pipeline that keys facts by period end alone will leak the future into a backtest, because it will use the restated value on a date when only the original existed. Key facts by filing date instead, and keep every version rather than only the latest.

Point-in-time facts in FinzData

import finzdata as yf

c = yf.Client()
rev = c.fundamentals(ticker="AAPL", concept="Revenues", as_of="2023-06-30")
stmt = c.statements("AAPL", statement="income", freq="quarterly")
val = c.valuation("AAPL", start="2009-01-01")

From raw facts to usable data

Raw XBRL needs work before it is usable: concept names vary across filers and years, units need normalizing, and statements must be assembled from tagged concepts. FinzData does that assembly and serves the result as point-in-time fundamentals keyed by filing date, plus financial statements, earnings release dates from 8-K Item 2.02 since 2004, and daily point-in-time valuation — P/E, P/B, P/S, EV/EBITDA, market cap and dividend yield — from 2009.

The free tier covers the last 12 months of every dataset with 1,000 API calls per day, so you can check the assembled data against the raw JSON before committing to it.

Frequently asked questions

Do I need an API key for SEC XBRL?

No. The endpoints are free and unauthenticated, but every request must send a User-Agent header identifying you or your company with a contact email.

How many requests can I make to the SEC API?

The SEC's fair-access guidance caps automated traffic at 10 requests per second. Cache companyfacts locally rather than re-fetching it.

What is the difference between companyfacts and frames?

companyfacts returns all facts for one company; frames returns one concept for all companies in one period. Use the first for deep dives, the second for screens.

Does SEC XBRL include restatements?

Yes. Restated values arrive in later filings, which is why you must key facts by filing date to keep a backtest point-in-time.

How do I get point-in-time fundamentals in Python?

Key each fact by its filing date and keep every version, or use a vendor that does. FinzData serves XBRL fundamentals point-in-time by filing date.