EDGAR is one of the few genuinely open, genuinely good government data sources: no API key, no account, structured JSON, decades of history. The trap isn't access — it's that "the EDGAR API" is really two systems with different hosts, different shapes and different jobs. Knowing which is which is 80% of the battle.
The two systems, side by side
Structured data, keyed by CIK
Give it a company's CIK and it hands back that company's filing index (/submissions/) or its standardized XBRL financial facts (/api/xbrl/companyfacts/). This is where you go when you already know whose data you want.
Full-text search, keyed by words
The /LATEST/search-index endpoint searches the actual text inside every filing since 2001. You go here when you don't know the company yet — "who mentioned going concern last quarter" — and it returns accession numbers to look up.
The workflow that confuses people is when they need both: search to discover filings by content, then data.sec.gov or the raw Archives tree to read them. Search never returns the document body; it returns pointers. Plan for the two-step.
Step zero: ticker to CIK
Almost everything on data.sec.gov is keyed by CIK — the Central Index Key — not by ticker. A ticker is a marketing handle that can change hands; the CIK is permanent. The SEC publishes the full map as a single file:
curl -s -A "Acme Research research@acme.com" \
https://www.sec.gov/files/company_tickers.json | head
# {"0":{"cik_str":320193,"ticker":"AAPL","title":"Apple Inc."}, ...}
Cache that file, look up your ticker, then zero-pad the CIK to 10 digits for the data endpoints — Apple's 320193 becomes CIK0000320193. Forgetting the padding is the single most common 404 people hit here.
Reading a company's filing history
With a padded CIK, one call gives you the entire recent filing index — every form, date and accession number:
curl -s -A "Acme Research research@acme.com" \
https://data.sec.gov/submissions/CIK0000320193.json
Inside, filings.recent is a columnar structure: parallel arrays for form, filingDate, accessionNumber and primaryDocument. To build a document URL, strip the dashes from the accession number and slot it into the Archives path. Companies with very long histories spill older filings into separate JSON files listed under filings.files — don't assume recent is everything.
Form types worth filtering on
EDGAR has hundreds of form types; a handful carry most of the signal people actually want:
| Form | What it is | Why you'd pull it |
|---|---|---|
10-K | Annual report | The full-year financials, risk factors and MD&A narrative. |
10-Q | Quarterly report | Interim financials between annuals — trend the quarters. |
8-K | Material event | Real-time signal: M&A, exec changes, guidance, bankruptcy. |
Form 4 | Insider transaction | Officers and directors buying or selling their own stock. |
13F-HR | Institutional holdings | What the big funds held at quarter end. |
S-1 | IPO registration | A company about to go public, with first-time financials. |
Skipping the parse: XBRL company facts
You usually don't need to parse a 10-K's HTML to get the numbers. The SEC already extracted them as XBRL. The companyfacts endpoint returns every tagged financial fact a company has ever reported, each with the period and the filing it came from:
curl -s -A "Acme Research research@acme.com" \
"https://data.sec.gov/api/xbrl/companyfacts/CIK0000320193.json"
# us-gaap/Revenues, us-gaap/NetIncomeLoss, us-gaap/Assets, ...
# each as a time series of {start, end, val, form, accn}
This is the cleanest path to "revenue, net income and EPS for the last ten years" without touching a single document. The one gotcha: companies tag the same concept under slightly different US-GAAP elements over time (Revenues vs RevenueFromContractWithCustomerExcludingAssessedTax), so a robust pull checks a few candidate tags and coalesces.
Full-text search for discovery
When you don't know the company, search the words. The endpoint behind EDGAR's full-text search returns ranked hits with the company, form and accession number:
curl -s -A "Acme Research research@acme.com" \
"https://efts.sec.gov/LATEST/search-index?q=%22supply+chain+disruption%22&forms=10-K&dateRange=custom&startdt=2026-01-01&enddt=2026-06-30"
Use exact phrases in quotes, narrow with forms= and a date range, and remember the corpus only goes back to 2001. The result set is for finding the needle — once you have the accession number, you go back to data.sec.gov or the Archives to actually read it.
User-Agent identifying who you are (a name and email is the convention) and to stay under roughly 10 requests per second. There's no key to revoke, so enforcement is blunt: exceed it and your IP gets a temporary block from the whole of sec.gov. A default python-requests User-Agent with no contact info is the fastest way to get rate-limited. Set the header, add a small delay, and you'll never hit it.Both systems, one clean output
Our SEC EDGAR Actor handles the CIK padding, the submissions/XBRL split, full-text search and the fair-access throttling — and returns filings, standardized financials or search hits as one tidy JSON feed.
Run the SEC EDGAR Actor → Or get done-for-you leadsA sane mental checklist
Before you write the first request, answer one question: do you know which company you want? If yes, you live on data.sec.gov — map ticker to CIK, pad it, pull submissions or company facts. If no, you start on efts.sec.gov — search the text, collect accession numbers, then cross over. Keep the descriptive User-Agent on every call, stay polite on the rate, and EDGAR is one of the most pleasant data sources on the public web.
Disclosure: links to Apify on this page are affiliate links, marked rel="sponsored". If you create a paid account through them we may earn a commission at no extra cost to you. We recommend Apify because we build and ship Actors on it ourselves, including the SEC EDGAR Actor linked above.