Back to Blog

SEC EDGAR Full-Text Search API (efts.sec.gov) — Complete Guide with Examples

Search the full text of every SEC filing ever submitted. The EDGAR Full-Text Search (EFTS) API at efts.sec.gov gives you free, programmatic access to billions of words across millions of documents.

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:

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