13F Filings API: Pull Any Fund's Holdings as JSON (2026)
Every quarter, the biggest investors in the market have to show their hand. Berkshire, Bridgewater, every fund over $100 million.
There is a catch. They show it 45 days late, and they only show the long side.
That filing is the 13F, and it is one of the most-read documents on SEC EDGAR. Here is what is in it, how to pull a fund's holdings as clean JSON, the parsing traps that quietly wreck the raw route, and where the data misleads you.
GET /v1/holdings/{fund}: positions aggregated by CUSIP, resolved to tickers, and diffed against the prior quarter. Value reporting changed from thousands to whole dollars on January 3, 2023, which is the trap that ruins most homemade parsers.What is a 13F filing?
A 13F is the quarterly report big institutional managers must file to disclose their holdings. Under Section 13(f) of the Securities Exchange Act, any manager with discretion over more than $100 million in covered US securities files within 45 days of each quarter's end, per Investor.gov. It is the clearest public window into what the smart money owns.
There are two versions, and the difference matters.
The one you want is the 13F-HR, the holdings report with the actual positions. A 13F-NT is just a notice that says another manager reports those holdings. Filter for 13F-HR or you will pull empty notices.
This is not a niche document. Over 5,000 managers file, per the 2024 rulemaking petition to modernize the rule, and roughly 3,000 to 4,000 file in any given quarter, per sec-api.io's dataset notes. Funds get read and copied off these filings within minutes of hitting EDGAR.
What is inside a 13F information table?
The information table is where the holdings live. It lists one row per position, and each row carries eight fields: issuer name, title of class, CUSIP, market value, share or principal amount, the SH or PRN type, put or call, investment discretion, and voting authority, per the SEC's Form 13F data sets. The SEC has required XML for this table since 2013 Q2, so it parses cleanly.
One number burns people more than any other: the value units changed.
For years, 13F value was reported in thousands. The SEC's 2022 amendment to Form 13F, adopted June 23, 2022 and effective January 3, 2023, switched it to whole dollars.
So the unit depends on the filing date. A 2021 filing that reads 1,743,219 means about $1.74 billion. A 2024 filing that reads 1,743,219 means about $1.7 million. Assume the wrong era and your numbers are off by three orders of magnitude.
And notice what is not there. No purchase price, no cost basis, no trade dates. A 13F is a snapshot at quarter-end, nothing about how or when the manager got there.
How do you get 13F holdings as JSON?
The fastest path is a hosted endpoint that returns the parsed table. With Edgrapi that is GET /v1/holdings/{fund}: pass a name like berkshire, a CIK, or a filer ticker like BRK-B, and you get every position back as JSON, with the issuer, CUSIP, resolved ticker, value in whole dollars, shares, percent of the book, and a new-or-added-or-reduced tag against last quarter. No XML parsing, no CUSIP crosswalk to build.
import requests
r = requests.get(
"https://api.edgrapi.com/v1/holdings/berkshire",
headers={"X-API-Key": "edgr_your_key"},
params={"limit": 10, "changes": True},
)
h = r.json()
print(h["manager"], h["period"])
for p in h["positions"]:
print(p["ticker"], p["value"], p["change"]["status"])
# AAPL 66000000000 reduced
# BAC 31000000000 unchanged
That is the whole job in one call. The response already handles the value units, so you never touch the thousands-versus-dollars trap.
The raw SEC route still works if you want to own the pipeline. Resolve the manager to a CIK, list its 13F-HR filings, fetch the information table XML, and parse the rows. It is free and needs only a User-Agent header, which we covered in the guide to the SEC EDGAR API key. The friction is the CIK: most managers are private, so you find them by name in EDGAR once and reuse the CIK every quarter.
What do developers build with 13F holdings?
Almost everything built on 13F data is quarter-over-quarter change work. The two you see most are crowding signals, which stocks the most funds are piling into at once, and clone portfolios that mirror a manager's book. Both are institutional-flow reads, and both come from diffing this quarter against last, so the change tag on each position matters more than the raw list.
This is why a flat holdings dump is only half of what you want.
"What is this fund buying and selling" is just this quarter's book minus last quarter's. Edgrapi's /v1/holdings tags every position new, added, reduced, or unchanged and lists the exits separately, so you read the delta instead of computing it. Point a screen at the new and added names across a set of funds and you have a crowding board in a few calls.
Why does the raw 13F table double-count a position?
Because one fund can report the same holding under several sub-managers. A large firm splits its book across internal managers, and each files its slice, so a naive parser that sums every row inflates the real position. The fix is to aggregate by CUSIP, summing shares and value across the duplicate rows into one line per security. Edgrapi's /v1/holdings does this before it returns anything, which is why its Apple line matches the fund's actual stake instead of double-counting it.
This is the single most common bug in homemade 13F pipelines.
You see a fund holding what looks like 400 million shares of one name, and half of it is the same block reported twice under two managers. Aggregate by CUSIP first, then rank.
Is a 13F put a bullish holding?
No. A put listed in a 13F is a bearish bet, not a long position, and counting it as ownership is the classic 13F mistake. The information table has a put-or-call column exactly for this, but most raw parsers ignore it and fold options into the share totals. A fund can show a large "position" in a stock that is actually a put against it. Read the put-or-call field, or use an endpoint that carries it, before you call anything a holding.
The other half of making 13F data useful is enrichment. A 13F tells you what a fund owns, not whether any of it is worth owning.
Each position already carries a ticker in the parsed response, so you pull fundamentals and ratios for the underlying company and rank the book by margins, growth, and valuation instead of position size alone. With Edgrapi that is /v1/fundamentals and /v1/ratios on the resolved ticker.
How do you pull a fund's 13F by ticker versus CIK?
You identify the fund three ways, and only one needs a ticker. Edgrapi's /v1/holdings takes a known name (berkshire, burry, pershing-square), a raw CIK, or a filer ticker when the manager is itself public like BRK-B. On the raw SEC route you always go by CIK, because a company ticker such as AAPL is the company, not a fund, and has no 13F of its own.
That last point trips people constantly.
You cannot ask "who holds AAPL" with a holdings call. AAPL is an operating company; it files no 13F. To see who holds a company, you want the 13D and 13G filings instead, covered in the 13D/13G guide.
What are the limits of 13F data?
Two limits decide how much you can trust a 13F. The 45-day filing lag means a position opened early in a quarter can be about 135 days old by the time it is public. And 13F is long-only: it leaves out short positions, most derivatives, non-US holdings, and cash, per this Yahoo Finance breakdown of the Form 13F trap, so what you see is a partial book.
That lag is not a small thing.
The 45-day window has stood since 1979, and the Society for Corporate Governance, NIRI, and the NYSE petitioned the SEC in 2024 to cut it to five business days. Until that changes, treat 13F as a map of where money sat last quarter, not where it is now.
So use it for what it is good at: seeing which names funds are crowding into, and watching how positioning shifts over several quarters. Do not use it to time a trade.
Raw EDGAR, a Python library, or a hosted API: which should you use?
Pick by how much parsing you want to own. The raw SEC route is free but you write the XML parser, the CUSIP aggregation, and the ticker crosswalk yourself. A Python library like edgartools does that parsing locally. A hosted API returns the finished JSON over one call, already deduped and diffed, which is the fastest path if you would rather not maintain a parser.
| Raw SEC EDGAR | edgartools (library) | Hosted API (Edgrapi) | |
|---|---|---|---|
| Cost | Free | Free, open source | Free tier, then paid |
| Holdings table | You parse the XML | Parsed in Python | Parsed JSON, one call |
| CUSIP aggregation | You build it | Handled | Handled |
| Value units normalized | You handle it | Handled | Handled |
| Quarter-over-quarter diff | You build it | You build it | Built in (new/added/reduced/exited) |
| Runs where | Your pipeline | Your Python process | Any language, over HTTP |
| Best for | Full custom pipelines | Python-native research | Apps in any stack, fast |
If you live in Python and want the data local, edgartools is excellent and free. If you are shipping an app in any language and want deduped, diffed holdings without owning a parser, the hosted call gets you there for free to start.
Start: read one fund's book
Pick a fund you actually follow. Call /v1/holdings with its name, and you have its long positions with values, tickers, and quarter-over-quarter changes in one response.
Then judge it. The positions already carry tickers, so pull ratios for the top few names and see which holdings actually have the margins, which are cheap, and which are just big. The free tier is 100 credits with no card, which covers a fund's book in one pass. Point it at https://api.edgrapi.com and start with the biggest position.
Frequently asked questions
What is an SEC 13F filing?
A 13F is a quarterly report that institutional investment managers with over $100 million in US-listed securities must file with the SEC. It lists their long positions: each holding's issuer, CUSIP, market value, and share count. Managers file it within 45 days of each quarter's end, under Section 13(f), so it is a delayed, long-only snapshot of where big money sits.
Who has to file a 13F?
Any institutional investment manager with discretion over more than $100 million in Section 13(f) securities, mostly US-listed stocks and options. That sweeps in hedge funds, mutual funds, pensions, banks, and registered advisers. The SEC estimates over 5,000 managers file each quarter. Once you cross the threshold you keep filing for the next year even if your assets drop back below it.
How do I get 13F holdings as JSON?
The fastest way is a hosted endpoint that returns the parsed table. Edgrapi's GET /v1/holdings/{fund} takes a name, a CIK, or a filer ticker and returns each position as JSON, aggregated by CUSIP and resolved to a ticker. The raw route is free too: find the manager's CIK, list its 13F-HR filings, and parse the information table XML yourself.
What information is in a 13F filing?
The information table reports one row per holding with eight fields: issuer name, title of class, CUSIP, market value, share or principal amount, the SH or PRN type, put or call, investment discretion, and voting authority. Value was reported in thousands until the SEC's 2022 amendment; since January 3, 2023 it is reported in whole dollars, so the unit depends on the filing date.
What are the limitations of 13F data?
Two big ones. The 45-day filing lag means a position opened early in the quarter can be roughly 135 days old before you see it. And 13F is long-only: it excludes short positions, most derivatives, non-US holdings, and cash, so it is a partial view. The 45-day window has stood since 1979, and industry groups have asked the SEC to shorten it to five business days.
Can I get a hedge fund's 13F holdings by ticker?
Edgrapi's /v1/holdings takes a fund name, a CIK, or a filer ticker when the manager is public like BRK-B, and returns the parsed holdings either way. A company ticker such as AAPL will not work, because AAPL is an operating company with no 13F of its own. To see who holds a company, use the 13D and 13G filings instead.