DEV Community

Alex Spinov
Alex Spinov

Posted on

SEC EDGAR API: How I Built a Free Stock Research Tool (No API Key Needed)

Last month, a friend asked me to help him analyze Tesla's financial filings. He was paying $50/month for a stock research tool.

I built him a free alternative in 2 hours using the SEC EDGAR API. Here's exactly how.

Why SEC EDGAR?

Every public company in the US must file financial reports with the SEC. These filings — 10-K (annual), 10-Q (quarterly), 8-K (events) — are all available for free through the EDGAR API.

No API key required. Just a User-Agent header with your email.

Setup: Zero Dependencies

import requests
import json

HEADERS = {
    "User-Agent": "MyApp/1.0 (your-email@example.com)"
}
BASE_URL = "https://efts.sec.gov/LATEST"
Enter fullscreen mode Exit fullscreen mode

That's it. No signup, no OAuth, no rate limit anxiety.

Step 1: Find Any Company by Name

def search_company(query):
    url = f"{BASE_URL}/search-index?q={query}&dateRange=custom&startdt=2024-01-01&enddt=2025-12-31"
    response = requests.get(url, headers=HEADERS)
    data = response.json()

    for hit in data.get("hits", {}).get("hits", [])[:5]:
        source = hit["_source"]
        print(f"{source["entity_name"]} | CIK: {source["entity_id"]} | {source["file_date"]}")

search_company("Tesla")
# Tesla Inc | CIK: 0001318605 | 2025-02-18
Enter fullscreen mode Exit fullscreen mode

Step 2: Get Company Filings

Once you have the CIK number, you can pull all filings:

def get_filings(cik, filing_type="10-K"):
    # CIK must be 10 digits, zero-padded
    cik_padded = str(cik).zfill(10)
    url = f"https://data.sec.gov/submissions/CIK{cik_padded}.json"

    response = requests.get(url, headers=HEADERS)
    data = response.json()

    filings = data["filings"]["recent"]
    for i in range(len(filings["form"])):
        if filings["form"][i] == filing_type:
            print(f"{filings["filingDate"][i]} | {filings["primaryDocument"][i]}")

get_filings(1318605, "10-K")
# 2025-01-29 | tsla-20241231.htm
# 2024-01-29 | tsla-20231231.htm
Enter fullscreen mode Exit fullscreen mode

Step 3: Get Financial Facts (The Gold Mine)

This is where it gets powerful. The Company Facts API gives you structured financial data:

def get_financials(cik):
    cik_padded = str(cik).zfill(10)
    url = f"https://data.sec.gov/api/xbrl/companyfacts/CIK{cik_padded}.json"

    response = requests.get(url, headers=HEADERS)
    data = response.json()

    # Get revenue (us-gaap taxonomy)
    revenue = data["facts"]["us-gaap"].get("Revenues", {})
    units = revenue.get("units", {}).get("USD", [])

    for entry in units[-5:]:
        if entry.get("form") == "10-K":
            print(f"{entry["fy"]}: ${entry["val"]:,.0f}")

get_financials(1318605)
# 2022: $81,462,000,000
# 2023: $96,773,000,000  
# 2024: $97,690,000,000
Enter fullscreen mode Exit fullscreen mode

Free. Structured. Straight from the source. No scraping needed.

Step 4: Full-Text Search Across All Filings

def search_filings(keyword, company=None):
    url = f"{BASE_URL}/search-index?q=%22{keyword}%22&dateRange=custom&startdt=2024-01-01"
    if company:
        url += f"&entityName={company}"

    response = requests.get(url, headers=HEADERS)
    hits = response.json().get("hits", {}).get("hits", [])

    for hit in hits[:3]:
        s = hit["_source"]
        print(f"{s["entity_name"]} | {s["file_date"]} | {s["file_description"]}")

search_filings("artificial intelligence", "Apple")
Enter fullscreen mode Exit fullscreen mode

Search for "bankruptcy", "restructuring", "AI" — across ALL public companies.

Real Use Case: Compare Revenue Growth

def compare_companies(ciks, metric="Revenues"):
    for name, cik in ciks.items():
        cik_padded = str(cik).zfill(10)
        url = f"https://data.sec.gov/api/xbrl/companyfacts/CIK{cik_padded}.json"
        data = requests.get(url, headers=HEADERS).json()

        vals = data["facts"]["us-gaap"].get(metric, {}).get("units", {}).get("USD", [])
        annual = [v for v in vals if v.get("form") == "10-K"][-2:]

        if len(annual) >= 2:
            growth = (annual[-1]["val"] - annual[-2]["val"]) / annual[-2]["val"] * 100
            print(f"{name}: {growth:+.1f}% YoY")

compare_companies({
    "Tesla": 1318605,
    "Apple": 320193,
    "Microsoft": 789019,
    "Google": 1652044
})
Enter fullscreen mode Exit fullscreen mode

What My Friend Saved

Tool Cost Data Quality
Bloomberg Terminal $2,000/mo Best
Yahoo Finance API $50/mo Good
SEC EDGAR API $0 Direct from source

He cancelled his subscription the same day.

Tips

  1. Rate limit: 10 requests/second. Add time.sleep(0.1) between calls
  2. User-Agent is required — use your real email, SEC will block generic agents
  3. XBRL data goes back to 2009 for most companies
  4. Bulk downloads available at https://www.sec.gov/Archives/edgar/full-index/

What would you build with free access to every US public company's financial data?

I'm building more free API tutorials — drop a comment if there's a specific API you want covered.


I publish daily tutorials on free APIs and developer tools. Follow for more.

Top comments (0)