The SEC provides free programmatic access to all EDGAR filing data through their API. This guide shows you how to access company information, filing histories, structured XBRL financial data, and full-text search, without any API keys or paid subscriptions. If you just want to read filings without writing code, you can also browse companies on TL;DR Filing or jump straight to a ticker via the A-Z ticker index.
Is the SEC EDGAR API Free?
Yes, completely. There is no API key, no sign-up, no OAuth flow, and no billing. The SEC's EDGAR data APIs on data.sec.gov and the full-text search API on efts.sec.gov are public services. The only rules are the fair access rules described below: identify yourself with a User-Agent header and stay under 10 requests per second.
Rate Limits and Fair Access Rules
The SEC does not use API keys to control access. Instead it enforces a fair access policy that applies to everyone:
- Maximum 10 requests per second. This is a hard ceiling per user. Going over it can get your IP address temporarily blocked (you will see HTTP 403 or 429 responses). In practice, adding a ~100ms delay between requests keeps you safely under the limit.
- Declare a User-Agent header. Every request should include a User-Agent identifying you or your company plus a contact email, for example
User-Agent: YourName email@domain.com. Requests without one are commonly rejected with a 403 error. - No API key needed. There is nothing to register for and nothing to rotate.
- No daily quotas. As long as you respect the per-second limit, you can pull as much data as you need. For bulk work, the SEC also publishes nightly bulk data files (companyfacts.zip and submissions.zip) so you do not have to crawl endpoint by endpoint.
curl -H "User-Agent: YourName email@domain.com" \
"https://data.sec.gov/submissions/CIK0000320193.json"
The Three Main Endpoint Families
Nearly everything you will do with the EDGAR API uses one of three endpoint families on data.sec.gov. In every URL, the CIK must be zero-padded to 10 digits.
1. Submissions: a company's filing history
https://data.sec.gov/submissions/CIK##########.json
# Example (Apple):
https://data.sec.gov/submissions/CIK0000320193.json
Returns company metadata (name, tickers, SIC code, addresses) plus the complete filing history: form types (10-K, 10-Q, 8-K, and more), filing dates, accession numbers, and document links.
2. CompanyFacts: every XBRL fact a company has reported
https://data.sec.gov/api/xbrl/companyfacts/CIK##########.json
# Example (Apple):
https://data.sec.gov/api/xbrl/companyfacts/CIK0000320193.json
One large JSON document with all of a company's structured financial data across every filing: revenue, net income, assets, share counts, and hundreds of other concepts, each with full history.
3. CompanyConcept: one concept for one company
https://data.sec.gov/api/xbrl/companyconcept/CIK##########/us-gaap/{Tag}.json
# Example (Apple's net income):
https://data.sec.gov/api/xbrl/companyconcept/CIK0000320193/us-gaap/NetIncomeLoss.json
When you only need a single metric, this endpoint returns that one concept's full history in a much smaller payload than CompanyFacts.
Full-Text Search API (efts.sec.gov)
The EDGAR full-text search API lets you search the text of filings from 2001 onward. It lives on a different host than the XBRL endpoints:
https://efts.sec.gov/LATEST/search-index?q={query}
# Search for an exact phrase:
https://efts.sec.gov/LATEST/search-index?q=%22supply+chain+disruption%22
# Restrict to a form type and date range:
https://efts.sec.gov/LATEST/search-index?q=%22cybersecurity+incident%22&forms=8-K&dateRange=custom&startdt=2026-01-01&enddt=2026-06-30
Results come back as JSON with matching accession numbers, filer names, CIKs, form types, and filing dates. This is the same backend that powers the EDGAR full-text search page at sec.gov/edgar/search. The same fair access rules apply: send a User-Agent header and stay under 10 requests per second. URL-encode your query (quotes become %22, spaces become + or %20).
Inside companyfacts.json: Structure Walkthrough
The CompanyFacts response has a consistent shape. At the top level:
{
"cik": 320193,
"entityName": "Apple Inc.",
"facts": {
"dei": { ... },
"us-gaap": {
"Revenues": {
"label": "Revenues",
"description": "...",
"units": {
"USD": [
{
"start": "2024-09-29",
"end": "2025-09-27",
"val": 123456000000,
"form": "10-K",
"fy": 2025,
"fp": "FY",
"filed": "2025-10-31"
}
]
}
}
}
}
}
cik: the company's Central Index Key as an integer (not zero-padded here).entityName: the registrant's official name.facts: grouped by taxonomy.deiholds entity information (shares outstanding, public float);us-gaapholds the financial statement concepts. Foreign filers may useifrs-fullinstead.facts.us-gaap.{Tag}.units: each concept's values grouped by unit (USD,shares,USD/shares). Each entry carries the period (start/end), the value (val), and which filing it came from (form,fy,fp,filed).
The practical pattern: pick a tag under facts["us-gaap"], pick a unit, filter by form (10-K for annual, 10-Q for quarterly), and sort by end to get the latest value.
CIK Quick Reference for Popular Tickers
API URLs require CIKs zero-padded to 10 digits. Here are the CIKs for commonly requested companies (each links to its TL;DR Filing company page):
| Company | Ticker | Zero-Padded CIK | CompanyFacts URL |
|---|---|---|---|
| Apple | AAPL | 0000320193 | .../companyfacts/CIK0000320193.json |
| Microsoft | MSFT | 0000789019 | .../companyfacts/CIK0000789019.json |
| NVIDIA | NVDA | 0001045810 | .../companyfacts/CIK0001045810.json |
| Amazon | AMZN | 0001018724 | .../companyfacts/CIK0001018724.json |
| Alphabet | GOOGL | 0001652044 | .../companyfacts/CIK0001652044.json |
| Tesla | TSLA | 0001318605 | .../companyfacts/CIK0001318605.json |
| Meta | META | 0001326801 | .../companyfacts/CIK0001326801.json |
| Berkshire Hathaway | BRK.B | 0001067983 | .../companyfacts/CIK0001067983.json |
| Oracle | ORCL | 0001341439 | .../companyfacts/CIK0001341439.json |
| Adobe | ADBE | 0000796343 | .../companyfacts/CIK0000796343.json |
Note: CIKs must be zero-padded to 10 digits in API URLs. Apple's CIK is 320193, but the URL requires CIK0000320193. Need a ticker not listed here? Every company page on this site is reachable from the A-Z ticker index, or download the SEC's own mapping at sec.gov/files/company_tickers.json.
Getting Started
The SEC requires a User-Agent header identifying yourself:
curl -H "User-Agent: YourName email@domain.com" \
"https://data.sec.gov/submissions/CIK0000320193.json"
JavaScript Example
async function getCompanyData(cik) {
const response = await fetch(`https://data.sec.gov/submissions/CIK${cik.padStart(10, '0')}.json`, {
headers: {
'User-Agent': 'YourName email@domain.com'
}
});
return response.json();
}
// Get Apple's data
const appleData = await getCompanyData('320193');
Key API Features
1. Company Submissions
Get all filings for a company:
- Recent filings (10-K, 10-Q, 8-K, etc.)
- Filing dates and accession numbers
- Document links and descriptions
- XBRL availability indicators
2. XBRL Financial Data
Access structured financial metrics:
- Revenue, net income, assets, liabilities
- Historical quarterly and annual data
- Multiple units (USD, shares, etc.)
- Form context (10-K vs 10-Q)
3. Rate Limiting
The API has generous limits:
- 10 requests per second
- No daily limits
- No API key required
- Free for all users
Practical Examples
Example 1: Get Company Revenue
async function getRevenue(cik) {
const url = `https://data.sec.gov/api/xbrl/companyconcept/CIK${cik.padStart(10, '0')}/us-gaap/Revenues.json`;
const response = await fetch(url, {
headers: { 'User-Agent': 'YourName email@domain.com' }
});
const data = await response.json();
const annualData = data.units.USD.filter(item => item.form === '10-K');
return annualData.sort((a, b) => b.end.localeCompare(a.end));
}
Example 2: Compare Companies
async function compareMetrics(companies, metric) {
const results = {};
for (const [ticker, cik] of Object.entries(companies)) {
try {
const data = await getMetric(cik, metric);
results[ticker] = data[0]?.val; // Latest value
} catch (e) {
results[ticker] = null;
}
// Respect rate limit
await new Promise(resolve => setTimeout(resolve, 100));
}
return results;
}
// Usage
const results = await compareMetrics({
'AAPL': '320193',
'MSFT': '789019',
'GOOGL': '1652044'
}, 'Revenues');
Common XBRL Tags
Here are the most useful XBRL tags for financial analysis:
Income Statement
Revenues- Total revenueGrossProfit- Gross profitOperatingIncomeLoss- Operating incomeNetIncomeLoss- Net incomeEarningsPerShareDiluted- Diluted EPS
Balance Sheet
Assets- Total assetsLiabilities- Total liabilitiesStockholdersEquity- Shareholders' equityCashAndCashEquivalentsAtCarryingValue- CashLongTermDebt- Long-term debt
Cash Flow
NetCashProvidedByUsedInOperatingActivities- Operating cash flowNetCashProvidedByUsedInInvestingActivities- Investing cash flowNetCashProvidedByUsedInFinancingActivities- Financing cash flow
Error Handling
async function safeAPICall(url) {
try {
const response = await fetch(url, {
headers: { 'User-Agent': 'YourName email@domain.com' }
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
return await response.json();
} catch (error) {
console.error(`API call failed: ${error.message}`);
return null;
}
}
Building a Financial Dashboard
Here's a complete example for building a basic financial dashboard:
class SECAnalyzer {
constructor() {
this.baseURL = 'https://data.sec.gov';
this.userAgent = 'YourName email@domain.com';
}
async getCompanyOverview(cik) {
const submissions = await this.fetch(`/submissions/CIK${cik.padStart(10, '0')}.json`);
const facts = await this.fetch(`/api/xbrl/companyfacts/CIK${cik.padStart(10, '0')}.json`);
return {
name: submissions.name,
ticker: submissions.tickers?.[0],
sic: submissions.sic,
filings: submissions.filings.recent,
financials: this.extractKeyMetrics(facts)
};
}
extractKeyMetrics(facts) {
const metrics = {};
const gaap = facts.facts['us-gaap'] || {};
// Extract key metrics with error handling
['Revenues', 'NetIncomeLoss', 'Assets', 'StockholdersEquity'].forEach(tag => {
if (gaap[tag]?.units?.USD) {
const annual = gaap[tag].units.USD
.filter(item => item.form === '10-K')
.sort((a, b) => b.end.localeCompare(a.end))[0];
metrics[tag] = annual?.val || null;
}
});
return metrics;
}
async fetch(endpoint) {
const response = await fetch(`${this.baseURL}${endpoint}`, {
headers: { 'User-Agent': this.userAgent }
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return response.json();
}
}
Best Practices
- Always include User-Agent: Required by SEC
- Respect rate limits: Max 10 requests per second
- Cache responses: Data doesn't change frequently
- Handle errors gracefully: Not all companies have all metrics
- Validate data: Check for null values and outliers
- Use proper CIK format: Zero-padded to 10 digits
Quick Reference: SEC EDGAR API Endpoints
Quick lookup table for the most commonly used SEC EDGAR API endpoints:
| Endpoint Name | URL Pattern | Returns |
|---|---|---|
| Company Facts | data.sec.gov/api/xbrl/companyfacts/CIK{number}.json | All XBRL financial facts |
| Submissions | data.sec.gov/submissions/CIK{number}.json | Filing history and metadata |
| Company Concept | data.sec.gov/api/xbrl/companyconcept/CIK{number}/{taxonomy}/{tag}.json | Specific data point across periods |
| Full-Text Search | efts.sec.gov/LATEST/search-index?q={query} | Filing search results |
Code Examples
Here are complete working examples in different languages for fetching companyfacts data:
Python Example
import requests
def get_company_facts(cik):
"""Fetch companyfacts for a company by CIK number."""
cik_padded = str(cik).zfill(10)
url = f'https://data.sec.gov/api/xbrl/companyfacts/CIK{cik_padded}.json'
headers = {'User-Agent': 'YourName email@domain.com'}
response = requests.get(url, headers=headers)
return response.json()
# Get Apple facts
apple_facts = get_company_facts('320193')
gaap = apple_facts['facts'].get('us-gaap', {})
if 'Revenues' in gaap:
revenues = gaap['Revenues']['units'].get('USD', [])
latest = max(revenues, key=lambda x: x['end'])
print(f"Latest Revenue: {latest['val']:,}")
Node.js / JavaScript Example
async function getCompanyFacts(cik) {
const cikPadded = String(cik).padStart(10, '0');
const url = `https://data.sec.gov/api/xbrl/companyfacts/CIK${cikPadded}.json`;
const response = await fetch(url, {
headers: {'User-Agent': 'YourName email@domain.com'}
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return response.json();
}
const appleFacts = await getCompanyFacts('320193');
const revenues = appleFacts.facts['us-gaap']?.Revenues?.units?.USD || [];
const latest = revenues.sort((a, b) => new Date(b.end) - new Date(a.end))[0];
console.log(`Latest Revenue: $${latest?.val?.toLocaleString()}`);
cURL Command Line
curl -H "User-Agent: YourName email@domain.com" \
"https://data.sec.gov/api/xbrl/companyfacts/CIK0000320193.json" \
| jq '.facts."us-gaap".Revenues.units.USD | sort_by(.end) | .[-1]'
Troubleshooting
403 Forbidden Error
Problem: You get a 403 error when making API requests.
Solution: The SEC requires a User-Agent header. Include it in all requests:
headers: {
'User-Agent': 'YourCompanyName email@domain.com'
}
Rate Limiting
Problem: You're getting rate limited (HTTP 429 errors).
Solution: The SEC allows maximum 10 requests per second. Add delays:
// Wait 100ms between requests
await new Promise(resolve => setTimeout(resolve, 100));
CIK Padding Issues
Problem: API returns 404 or incorrect data.
Solution: CIK must be zero-padded to 10 digits:
- Apple: 320193 → CIK0000320193
- Microsoft: 789019 → CIK0000789019
FAQ
Is the SEC EDGAR API free?
Yes, completely free. No API key, no registration, no authentication, no paid tier. The only requirement is a User-Agent header identifying you with a contact email.
What are the SEC EDGAR API rate limits?
Maximum 10 requests per second per user, with no daily quotas. Exceeding the limit can get your IP temporarily blocked, so add roughly a 100ms delay between requests.
Does the SEC EDGAR API require an API key?
No. There is no API key and no authentication. You only need a User-Agent header such as "YourName email@domain.com". Requests without it are typically rejected with a 403 error.
What is data.sec.gov/api/xbrl/companyfacts/CIK0000320193.json?
That is the CompanyFacts endpoint for Apple (CIK 0000320193). It returns one JSON document with every XBRL-tagged financial fact Apple has reported, organized under facts.us-gaap with values, units, dates, and source forms.
What is the SEC EDGAR full-text search API?
The endpoint at efts.sec.gov/LATEST/search-index?q= searches the text of EDGAR filings from 2001 onward. It supports form-type and date filters and returns JSON with accession numbers and filing metadata.
How do I find a company's CIK number?
Search at sec.gov/cgi-bin/browse-edgar by name or ticker, or download the ticker-to-CIK map at sec.gov/files/company_tickers.json. Remember to zero-pad the CIK to 10 digits in API URLs.
Alternative: Use TL;DR Filing
While the SEC API is powerful, it can be complex to work with. Our TL;DR Filing platform sits on top of the same EDGAR data and provides:
- Pre-processed financial metrics on every company page
- AI-generated filing summaries
- Standardized company data
- Built-in error handling
- An A-Z ticker index covering thousands of public companies
Conclusion
The SEC EDGAR API provides free access to a wealth of financial data. Start with basic company lookups via the Submissions endpoint, pull structured financials from CompanyFacts, use CompanyConcept for single metrics, and reach for full-text search when you need to find filings by content. Remember to be respectful of the 10 requests per second limit and always include proper attribution in your User-Agent header.
For more complex analysis needs, consider using our TL;DR Filing platform which provides AI-powered insights on top of this raw SEC data.