What Is the EDGAR Full-Text Search API?
The SEC operates a full-text search system at efts.sec.gov that indexes every filing in the EDGAR database. Unlike the structured XBRL endpoints at data.sec.gov that return financial numbers, the EFTS API lets you search the actual text inside filings — 10-Ks, 10-Qs, 8-Ks, proxy statements, and every other form type.
This is incredibly powerful for research. You can find every filing that mentions "material weakness," track how often companies discuss "artificial intelligence" in their risk factors, or locate specific executive compensation clauses across thousands of companies.
The base endpoint is:
https://efts.sec.gov/LATEST/search-index?q=YOUR_QUERY
No API key is required. No authentication. Just include a proper User-Agent header and respect the rate limits.
API Endpoint and Query Parameters
The EFTS search endpoint accepts several query parameters that let you filter and refine your search:
| Parameter | Type | Description | Example |
|---|---|---|---|
| q | string | Search query. Supports exact phrases with quotes and boolean operators. | q="material weakness" |
| dateRange | string | Filter by filing date range. Use "custom" with startdt/enddt parameters. | dateRange=custom&startdt=2025-01-01&enddt=2025-12-31 |
| forms | string | Comma-separated list of form types to search within. | forms=10-K,10-Q |
| from | integer | Starting result index for pagination. Default: 0. | from=100 |
| size | integer | Number of results per page. Default: 10, max: 100. | size=50 |
Response Format
The API returns a JSON object containing the total hit count and an array of matching filings. Here is the structure of a typical response:
{
"query": { "from": 0, "size": 10, "q": "\"material weakness\"" },
"hits": {
"total": { "value": 15432, "relation": "eq" },
"hits": [
{
"_id": "0001234567-24-001234:filing-main.htm",
"_source": {
"file_date": "2025-03-15",
"period_of_report": "2024-12-31",
"form_type": "10-K",
"entity_name": "Example Corp",
"file_num": "001-12345",
"film_num": "",
"file_description": "Annual Report"
}
}
]
}
}
Each hit includes the accession number (embedded in _id), the form type, company name, filing date, and the reporting period. You can use the accession number to construct a direct link to the filing on EDGAR.
Python Examples
Basic Search
import requests
import time
HEADERS = {'User-Agent': 'YourName [email protected]'}
BASE_URL = 'https://efts.sec.gov/LATEST/search-index'
def search_filings(query, forms=None, start_date=None, end_date=None, size=10):
"""Search the full text of all SEC filings."""
params = {'q': query, 'size': size}
if forms:
params['forms'] = forms
if start_date and end_date:
params['dateRange'] = 'custom'
params['startdt'] = start_date
params['enddt'] = end_date
response = requests.get(BASE_URL, params=params, headers=HEADERS)
response.raise_for_status()
return response.json()
# Search for "material weakness" in 10-K filings from 2025
results = search_filings(
query='"material weakness"',
forms='10-K',
start_date='2025-01-01',
end_date='2025-12-31',
size=50
)
total = results['hits']['total']['value']
print(f'Found {total} filings mentioning "material weakness"')
for hit in results['hits']['hits']:
src = hit['_source']
print(f" {src['entity_name']} - {src['form_type']} ({src['file_date']})")
Paginating Through All Results
def search_all_filings(query, forms=None, max_results=500):
"""Paginate through EFTS results, respecting rate limits."""
all_hits = []
offset = 0
page_size = 100 # Maximum allowed
while offset < max_results:
params = {'q': query, 'from': offset, 'size': page_size}
if forms:
params['forms'] = forms
response = requests.get(BASE_URL, params=params, headers=HEADERS)
response.raise_for_status()
data = response.json()
hits = data['hits']['hits']
if not hits:
break
all_hits.extend(hits)
offset += page_size
# Respect SEC rate limit: 10 req/sec
time.sleep(0.15)
return all_hits
# Get up to 500 filings mentioning "artificial intelligence" in risk factors
ai_filings = search_all_filings('"artificial intelligence"', forms='10-K', max_results=500)
print(f'Retrieved {len(ai_filings)} filings')
JavaScript Examples
Basic Search with Fetch
const HEADERS = { 'User-Agent': 'YourName [email protected]' };
const BASE_URL = 'https://efts.sec.gov/LATEST/search-index';
async function searchFilings(query, { forms, startDate, endDate, size = 10 } = {}) {
const params = new URLSearchParams({ q: query, size });
if (forms) params.set('forms', forms);
if (startDate && endDate) {
params.set('dateRange', 'custom');
params.set('startdt', startDate);
params.set('enddt', endDate);
}
const response = await fetch(`${BASE_URL}?${params}`, { headers: HEADERS });
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return response.json();
}
// Find filings mentioning "cybersecurity incident" in 8-K filings
const results = await searchFilings('"cybersecurity incident"', {
forms: '8-K',
startDate: '2025-01-01',
endDate: '2025-12-31',
size: 50
});
console.log(`Total matches: ${results.hits.total.value}`);
results.hits.hits.forEach(hit => {
const s = hit._source;
console.log(` ${s.entity_name} - ${s.form_type} (${s.file_date})`);
});
Building a Filing URL from Search Results
function getFilingUrl(hit) {
// The _id contains the accession number and filename
// Format: "0001234567-24-001234:filename.htm"
const [accessionRaw, filename] = hit._id.split(':');
const accession = accessionRaw.replace(/-/g, '');
const accessionDashed = accessionRaw;
return `https://www.sec.gov/Archives/edgar/data/${accession.slice(0,10)}/${accessionDashed}/${filename}`;
}
// Get direct links to filings
results.hits.hits.forEach(hit => {
console.log(getFilingUrl(hit));
});
Use Cases
1. Finding Material Weakness Disclosures
Auditors are required to report material weaknesses in internal controls. Searching for this phrase in 10-K filings helps identify companies with accounting control issues:
# Find all 10-K filings with material weakness disclosures in 2025
results = search_filings(
'"material weakness in internal control"',
forms='10-K',
start_date='2025-01-01',
end_date='2025-12-31',
size=100
)
print(f'{results["hits"]["total"]["value"]} companies disclosed material weaknesses')
2. Tracking Risk Factor Mentions
Monitor how companies discuss emerging risks like AI regulation, climate change, or geopolitical tensions:
# Track AI regulation mentions over time
for year in range(2020, 2026):
results = search_filings(
'"artificial intelligence" AND "regulation"',
forms='10-K',
start_date=f'{year}-01-01',
end_date=f'{year}-12-31'
)
count = results['hits']['total']['value']
print(f'{year}: {count} filings mention AI regulation')
time.sleep(0.15)
3. Executive Compensation Clause Analysis
Search proxy statements (DEF 14A) for specific compensation structures:
# Find golden parachute clauses
results = search_filings(
'"golden parachute" OR "change of control payment"',
forms='DEF 14A',
size=100
)
for hit in results['hits']['hits']:
src = hit['_source']
print(f"{src['entity_name']}: {src['file_date']}")
Rate Limits and Best Practices
The EFTS API shares the same rate limits as other EDGAR endpoints:
- 10 requests per second maximum
- User-Agent header required — format:
CompanyName [email protected] - Exceeding limits results in a 403 block for approximately 10 minutes
- No daily limits — as long as you stay under 10 req/sec, you can make unlimited requests
For large-scale research, add a 150ms delay between requests and implement exponential backoff on errors. See our complete rate limits guide for detailed strategies.
FAQ
What is efts.sec.gov?
efts.sec.gov is the SEC's EDGAR Full-Text Search system. It provides a free API at efts.sec.gov/LATEST/search-index that lets you search the full text of all SEC filings by keyword, date range, form type, and more.
Does the EDGAR full-text search API require authentication?
No. The EFTS API is completely free and requires no API key or authentication. However, you must include a User-Agent header with your name and email address in all requests.
What is the rate limit for efts.sec.gov?
The SEC enforces a rate limit of 10 requests per second across all EDGAR APIs, including the full-text search endpoint. Exceeding this limit results in a temporary IP block (typically 10 minutes).
Can I search for specific phrases in SEC filings?
Yes. Wrap your search terms in double quotes within the q parameter to search for exact phrases. For example, q="material weakness" will find filings containing that exact phrase.
How many results can the EFTS API return?
The API returns up to 100 results per request using the size parameter (default is 10). You can paginate through results using the from parameter to access additional pages of results.
Related Guides
- Free SEC EDGAR API Guide — Complete overview of all EDGAR API endpoints
- SEC CIK Number Lookup Guide — Find any company's CIK number instantly
- Build a Stock Screener with the SEC EDGAR API — Python tutorial using XBRL financial data
- Download SEC 10-K Filings Programmatically — Python & JavaScript guide
- SEC EDGAR API Rate Limits & Best Practices — Avoid getting blocked