US Securities and Exchange Commission
SEC EDGAR APIs — Fundamentals as filed, every filing's index, and insider trades — from the regulator, not a reseller
When a number has to be the one in the filing — revenue, net income, shares outstanding — or you want the list of everything a company has filed. companyfacts gives the whole XBRL history of one company in one call; frames gives one metric across every filer for one period.
Reach for it when…
When a number has to be the one in the filing — revenue, net income, shares outstanding — or you want the list of everything a company has filed. companyfacts gives the whole XBRL history of one company in one call; frames gives one metric across every filer for one period.
Not for: Prices, ratios or screens (a data vendor computes those), non-US companies (EDINET for Japan, OpenDART for Korea), anything before XBRL (2009).
Units, revisions, traps
Units. XBRL values in the filing's units (USD, shares, pure). Each fact carries the period it covers — a 10-K revenue fact is a fiscal year, a 10-Q fact is a quarter or year-to-date.
Revisions. Restated numbers appear as new facts with a later filing date; the original fact stays. Filter on 'form' and 'fy' to avoid double-counting.
- The same concept appears under several tags (Revenues, RevenueFromContractWithCustomerExcludingAssessedTax); pick per company.
- Duration facts overlap: year-to-date Q3 includes Q1 and Q2 — use the 'frame' field (CY2024Q3) to get clean quarters.
- CIKs are ten digits, zero-padded, in the URL.
Classic mistake: Summing the four 10-Q revenue facts and the 10-K fact and getting two years' worth.
Three recipes
- Recipe 1 · A company's revenue history, as filed
- Recipe 2 · One metric across every filer (frames)
- Recipe 3 · Insider trades: the Form 4 list
Each recipe: Python · Excel · Sheets, with how to read the result. Python recipes run under pandas; recipe 1 is re-run by the weekly check where the source allows it.
How to use it in your own work
Copy the snippet, change the series id, read the result the way the footer says. Replace YOUR_…_KEY with your own key where one is needed.
Recipe 1A company's revenue history, as filed
# Apple: annual revenue from the XBRL facts (CIK 320193). Declare who you are or EDGAR refuses.
import requests, pandas as pd
H = {"User-Agent": "Your Name [email protected]"}
j = requests.get("https://data.sec.gov/api/xbrl/companyfacts/CIK0000320193.json", headers=H, timeout=60).json()
facts = j["facts"]["us-gaap"]["RevenueFromContractWithCustomerExcludingAssessedTax"]["units"]["USD"]
df = pd.DataFrame(facts)
fy = df[(df.form == "10-K") & (df.fp == "FY") & df.frame.notna() & ~df.frame.str.contains("Q", na=False)]
print(fy[["fy", "end", "val", "frame"]].drop_duplicates("frame").tail(6))- Not practical without code — the JSON is nested.
- Use the Python recipe or Full-Text Search on sec.gov for a single filing.
- Use the Python recipe; export to CSV.
Recipe 2One metric across every filer (frames)
# every company that reported Revenues for calendar 2024
import requests, pandas as pd
H = {"User-Agent": "Your Name [email protected]"}
j = requests.get("https://data.sec.gov/api/xbrl/frames/us-gaap/Revenues/USD/CY2024.json", headers=H, timeout=60).json()
df = pd.DataFrame(j["data"]).sort_values("val", ascending=False)
print(df[["entityName", "val", "end"]].head(10))- Use the Python recipe.
- Use the Python recipe.
Recipe 3Insider trades: the Form 4 list
# every Form 4 a company filed, newest first, from the submissions index
import requests, pandas as pd
H = {"User-Agent": "Your Name [email protected]"}
j = requests.get("https://data.sec.gov/submissions/CIK0000320193.json", headers=H, timeout=60).json()
f = pd.DataFrame(j["filings"]["recent"])
form4 = f[f.form == "4"][["filingDate", "accessionNumber", "primaryDocument"]]
print(form4.head(10))
# open one: https://www.sec.gov/Archives/edgar/data/320193/<accessionNumber without dashes>/<primaryDocument>- EDGAR Full-Text Search (efts.sec.gov/LatestSearch/) → filter form type 4 → export.
- Export from Full-Text Search and import.
Series → question map
The ids we use from SEC EDGAR APIs, each with the question it answers. The catalog's compare view reads the concept tags behind these rows.
| Series | Answers | Region | Concept |
|---|---|---|---|
| companyfacts | What did the company report, by year and quarter? | United States | fundamentals |
| frames | One metric across all filers for one period | United States | fundamentals |
| submissions | What has the company filed? | United States | filings |
| Form 4 | Are insiders buying or selling? | United States | insider |
Compare with
Same question, different source: OpenDART, EODHD, Twelve Data. The compare view lines up coverage, frequency, history and access side by side and lists what the combination makes possible.
Questions readers ask
Why does EDGAR return 403?
No User-Agent. Send 'Name email' in the header and stay under ten requests a second.
Is EDGAR data real-time?
Filings appear within minutes of acceptance; the XBRL APIs update as the filing is processed, usually the same day.
Where do I find a company's CIK?
www.sec.gov/cgi-bin/browse-edgar?company=name, or the company_tickers.json file at www.sec.gov/files/company_tickers.json.
Educational only — we explain, we never advise · snippet licence: public domain · corrections to [email protected], fixed within a day and logged in the changelog.