SEC EDGAR — filings, financials, full-text search
Verified May 16, 2026 · tested with live data.sec.gov + efts.sec.gov fetch (submissions, XBRL, search)
SEC EDGAR is the free, authoritative source for US corporate disclosure:
10-K/10-Q/8-K filings, standardized XBRL financial facts (cross-company
comparable), insider trades (Form 4), institutional holdings (13F), proxy
statements, and full-text search across everything. No API key — just a
User-Agent header. It is the corporate-finance backbone the
ZeroPaper pipeline uses for
governance, disclosure, and fundamentals work. This page is the distilled
access recipe.
- Cost: free, no paywall, no key.
- Auth: none — but a descriptive
User-Agentheader is mandatory. - Coverage: all US public-company filings; XBRL facts from ~2009.
- Home: https://www.sec.gov/edgar · API: https://data.sec.gov · Full-text: https://efts.sec.gov
Access
Section titled “Access”Option 1 — edgartools (preferred — structured data)
Section titled “Option 1 — edgartools (preferred — structured data)”# pip install edgartoolsfrom edgar import Company, set_identity
# Identity = your User-Agent. Required by the SEC. Keep it in .env, not here.set_identity("Your Name your@email.edu")
company = Company("AAPL") # ticker → CIK resolved for youtenks = company.get_filings(form="10-K")filing = tenks[0]print(filing.filing_date, filing.accession_no)
facts = company.get_facts() # XBRL, cross-company comparablerevenue = facts.to_pandas("us-gaap:Revenues")
form4 = company.get_filings(form="4")[0].obj() # insider tradesOption 2 — Direct REST API (no package)
Section titled “Option 2 — Direct REST API (no package)”import requestsheaders = {"User-Agent": "Your Name your@email.edu"} # mandatory
# All filings + metadata for a company (note 10-digit zero-padded CIK):requests.get("https://data.sec.gov/submissions/CIK0000320193.json", headers=headers).json()
# One XBRL concept across time:requests.get("https://data.sec.gov/api/xbrl/companyconcept/" "CIK0000320193/us-gaap/Revenues.json", headers=headers).json()
# Full-text search:requests.get("https://efts.sec.gov/LATEST/search-index?" "q=%22climate+risk%22&forms=10-K", headers=headers).json()Store the name/email in .env (e.g. SEC_EDGAR_NAME, SEC_EDGAR_EMAIL);
never hard-code them.
Gotchas (the ones that bite pipelines)
Section titled “Gotchas (the ones that bite pipelines)”The reason to read this page rather than the SEC docs. Verified against live endpoints on the date above.
- No
User-Agent→ HTTP 403. This is the #1 EDGAR failure. A request with no (or a defaultpython-requests) User-Agent is rejected outright — confirmed 403 live. Always send a descriptiveName emailstring. - Rate limit: 10 requests/second, hard.
edgartoolsthrottles for you; for the direct API addtime.sleep(0.1)between calls and never parallelize blindly — sustained bursts get the host IP blocked, not just throttled. - CIK must be 10-digit zero-padded in
data.sec.govURLs (CIK0000320193, notCIK320193or320193).edgartools’Company("TICKER")hides this; the raw API does not. - Use XBRL for cross-company work, not filing text. Narrative text and
table formatting vary by filer and year;
us-gaap:*XBRL facts are standardized and comparable. Only parse text when the datum isn’t tagged. - XBRL coverage starts ~2009 and tag usage drifts: revenue may be
us-gaap:Revenuesorus-gaap:RevenueFromContractWithCustomerExcludingAssessedTax. Check both. - Cache aggressively. Save XBRL facts to
data/*.parquetand check before re-downloading — re-pulling companyfacts for a panel will blow the rate limit fast. - Amendments & restatements.
10-K/Asupersedes10-K; a company can restate prior XBRL facts. Pin the accession number when reproducibility matters.
Key filing types
Section titled “Key filing types”| Form | Contents | Use for |
|---|---|---|
10-K | Annual report | Financials, risk factors, business description |
10-Q | Quarterly report | Interim financials |
8-K | Current report | Material events (M&A, earnings, mgmt changes) |
DEF 14A | Proxy statement | Executive comp, board, governance |
4 | Insider trades | Director/officer buy/sell transactions |
13F-HR | Institutional holdings | Quarterly positions of large investors |
S-1 | IPO registration | Pre-IPO financials, risk factors |
SC 13D/G | Beneficial ownership | >5% shareholder positions |
Common XBRL facts
Section titled “Common XBRL facts”| Concept | Tag |
|---|---|
| Revenue | us-gaap:Revenues / us-gaap:RevenueFromContractWithCustomerExcludingAssessedTax |
| Net income | us-gaap:NetIncomeLoss |
| Total assets | us-gaap:Assets |
| Total equity | us-gaap:StockholdersEquity |
| EPS (basic) | us-gaap:EarningsPerShareBasic |
| Shares outstanding | us-gaap:CommonStockSharesOutstanding |
| Cash | us-gaap:CashAndCashEquivalentsAtCarryingValue |
| Long-term debt | us-gaap:LongTermDebt |
| R&D expense | us-gaap:ResearchAndDevelopmentExpense |
Standard recipes
Section titled “Standard recipes”Panel of fundamentals across firms — loop tickers, pull get_facts(),
take the XBRL concept you need, cache each to parquet, then assemble:
from edgar import Companyimport pandas as pd
rows = []for t in ["AAPL", "MSFT", "GOOGL", "AMZN", "META"]: rev = Company(t).get_facts().to_pandas("us-gaap:Revenues") rows.append({"ticker": t, "rev_latest": rev.iloc[-1] if len(rev) else None})df = pd.DataFrame(rows)Full-text search for a research topic — efts.sec.gov/LATEST/search-index
returns hit counts and snippets; use it to scope a sample before downloading
filings (data["hits"]["total"]["value"]).
Insider-trading study — iterate a company’s Form 4 filings and read
.obj().transactions (a DataFrame of trades) per filing.
Citation
Section titled “Citation”Cite the filing and source, e.g.: Apple Inc., Form 10-K, fiscal year 2024, filed [date], accession [no.], U.S. Securities and Exchange Commission EDGAR; https://www.sec.gov/cgi-bin/browse-edgar?action=getcompany&CIK=0000320193, accessed YYYY-MM-DD. For XBRL facts, state the concept tag and the filing the value came from.