Warren Buffett just filed his latest 13F. Cathie Wood reshuffled her portfolio. A CEO quietly sold $50M worth of shares.
All of this is public data — the SEC requires it. But actually getting to it programmatically? That's where most people give up.
SEC EDGAR's website is a maze of SGML files, inconsistent formatting, and nested folders. I spent weeks parsing it and built an API so others don't have to. Here's what I learned and how to use it.
What Are 13F Filings?
Every institutional investment manager with over $100M in assets must file a 13F-HR with the SEC each quarter. This filing lists every equity position they hold — stock name, number of shares, and market value.
This is how you find out what Berkshire Hathaway, Bridgewater, or Renaissance Technologies actually own.
The Problem with Raw EDGAR Data
If you go to sec.gov/cgi-bin/browse-edgar and try to pull 13F data, you'll find:
- Filings are in XML/SGML with inconsistent schemas across years
- No unified search across companies and filing types
- Holdings are buried in
informationtable.xmlfiles - No simple way to compare quarter-over-quarter changes
- Rate limits that will throttle you after a few requests
I ended up building a pipeline that ingests all of this into ClickHouse and exposes it through a clean REST API.
Searching for Companies
First, find the company you want to track. Every company in EDGAR has a CIK (Central Index Key):
curl "https://edgar.dapdev.tech/companies/search?query=Tesla"
{
"results": [
{
"cik": 1318605,
"name": "Tesla, Inc.",
"ticker": "TSLA"
}
],
"total": 1,
"query": "Tesla"
}
Pulling 13F Holdings (The Good Stuff)
Once you have the CIK, you can pull their latest 13F holdings. Here's Berkshire Hathaway's portfolio:
curl "https://edgar.dapdev.tech/holdings/13f/1067983"
{
"cik": 1067983,
"company_name": "BERKSHIRE HATHAWAY INC",
"report_date": "2026-02-17",
"total_value_usd": 66858093626,
"total_holdings": 42,
"holdings": [
{
"name_of_issuer": "OCCIDENTAL PETE CORP",
"value_usd": 10894391643,
"shares": 264941431,
"share_type": "SH"
},
{
"name_of_issuer": "CHUBB LIMITED",
"value_usd": 10689854998,
"shares": 34249183,
"share_type": "SH"
},
{
"name_of_issuer": "KRAFT HEINZ CO",
"value_usd": 7896644337,
"shares": 325634818,
"share_type": "SH"
}
]
}
Berkshire's top 3 positions: Occidental Petroleum ($10.9B), Chubb ($10.7B), and Kraft Heinz ($7.9B). 42 total holdings worth $66.8 billion. This is live data from their latest filing.
Searching Filings by Type
You can search for specific filing types across any company:
curl "https://edgar.dapdev.tech/filings/search?query=Berkshire+Hathaway&type=13F&limit=5"
This returns recent 13F-HR filings with accession numbers. You can then use the accession number to get the full filing detail.
Tracking Insider Trades
SEC Form 4 filings disclose when company insiders (officers, directors, 10%+ shareholders) buy or sell shares. This is often a leading signal:
curl "https://edgar.dapdev.tech/insider/0000320193"
This returns all recent insider transactions for Apple (CIK 320193) — who traded, what they traded, how many shares, and whether it was a buy or sell.
Building Something Useful: A Python Portfolio Tracker
Here's a practical example — a script that tracks quarterly changes in any fund's portfolio:
import httpx
API = "https://edgar.dapdev.tech"
HEADERS = {"X-RapidAPI-Key": "your-key-here"}
def get_portfolio(cik: int) -> dict:
"""Get latest 13F holdings for a fund."""
resp = httpx.get(f"{API}/holdings/13f/{cik}", headers=HEADERS)
resp.raise_for_status()
return resp.json()
def top_positions(portfolio: dict, n: int = 10) -> None:
"""Print top N positions by value."""
holdings = sorted(
portfolio["holdings"],
key=lambda h: h["value_usd"],
reverse=True
)
total = portfolio["total_value_usd"]
print(f"\n{portfolio['company_name']} - {portfolio['report_date']}")
print(f"Total portfolio: ${total:,.0f}")
print(f"{'Position':<30} {'Value':>15} {'% of Portfolio':>15}")
print("-" * 62)
for h in holdings[:n]:
pct = (h["value_usd"] / total) * 100
print(f"{h['name_of_issuer']:<30} ${h['value_usd']:>14,.0f} {pct:>14.1f}%")
# Berkshire Hathaway
portfolio = get_portfolio(1067983)
top_positions(portfolio)
Output:
BERKSHIRE HATHAWAY INC - 2026-02-17
Total portfolio: $66,858,093,626
Position Value % of Portfolio
--------------------------------------------------------------
OCCIDENTAL PETE CORP $10,894,391,643 16.3%
CHUBB LIMITED $10,689,854,998 16.0%
KRAFT HEINZ CO $7,896,644,337 11.8%
MOODYS CORP $6,448,842,688 9.6%
ALPHABET INC $5,585,842,446 8.4%
VISA INC $2,910,002,197 4.4%
Who Uses This Data?
- Retail investors tracking what the "smart money" is doing
- Quant funds using institutional holdings as features in their models
- Financial journalists covering portfolio changes
- Compliance teams monitoring insider activity
- Fintech apps building portfolio analytics dashboards
Available Endpoints
| Endpoint | Description |
|---|---|
GET /companies/search |
Search companies by name or ticker |
GET /companies/{cik} |
Get company profile |
GET /filings/search |
Search filings by company and type |
GET /filings/{accession} |
Get full filing detail |
GET /holdings/13f/{cik} |
Latest 13F holdings |
GET /holdings/13f/{cik}/history |
Historical 13F filings |
GET /insider/{cik} |
Insider trading activity |
The API is available on RapidAPI with a free tier.
Why I Built This
SEC EDGAR is one of the richest free data sources in finance, but the raw data format makes it painful to work with. Commercial alternatives like Bloomberg Terminal or FactSet cost thousands per month.
I wanted something in between — structured, searchable, API-accessible SEC data for developers building financial tools. The backend uses ClickHouse for fast analytical queries across millions of filings.
If you're building anything finance-related and need SEC data, give it a try. Happy to answer questions in the comments.
Top comments (1)
I get {"detail":"Forbidden"}, is the api limit already used up?