SEC 13F Scraper - Fund Holdings
Pricing
from $0.70 / 1,000 holdings
SEC 13F Scraper - Fund Holdings
Institutional holdings with the part nobody sells: what changed. Positions opened, exited, added to and trimmed between quarters, classified on share count so a market move is never mistaken for a trade. Handles the 2023 units change and the split-row trap.
Pricing
from $0.70 / 1,000 holdings
Rating
0.0
(0)
Developer
Datalayer
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
19 days ago
Last modified
Categories
Share
SEC 13F Scraper — Fund Holdings & Quarterly Changes
Every manager running $100m+ files a quarterly 13F listing its US equity positions. Dumping that table is easy, and it is what every 13F scraper does. It is also wrong three ways.
The three traps
1. The values changed units in 2023 — silently, by a factor of 1000.
SEC amended Form 13F for filings made from 3 January 2023: values are whole dollars. Before that they were thousands. Berkshire Hathaway's own filings:
| Filed | tableValueTotal | Actually |
|---|---|---|
| 2022-11-14 | 296,096,640 | $296.1 billion |
| 2026-05-15 | 263,095,703,570 | $263.1 billion |
Read both literally and the 2022 portfolio comes out as $296 million. This Actor normalises everything to dollars and labels which convention each filing used.
2. One holding is filed as many rows.
The same CUSIP repeats once per internal manager group. Berkshire's Q1 2026
filing lists ALLY FINL INC three separate times. Row-dumping reports three
positions where there is one — and every weight, rank and count derived from it
is wrong.
Verified on the same filing: 90 rows collapse to 29 real positions, 18 of which were split. This Actor aggregates by CUSIP and tells you how many rows were merged, so the arithmetic is auditable.
3. Amendments replace a quarter; they do not add one.
A 13F-HR/A restates a period already filed. Treat it as another quarter and
you double-count; ignore it and you are reading data the filer has withdrawn.
This Actor keeps the latest filing per period and names the accession it
supersedes.
What nobody sells: the diff
A list of positions is a snapshot. What moved is the information. Every quarter is compared against the one before it and each position is labelled:
| Action | Meaning |
|---|---|
NEW | Position opened this quarter |
EXITED | Position closed entirely |
ADDED | Share count up by more than the threshold |
TRIMMED | Share count down by more than the threshold |
HELD | No meaningful change |
Decided on share count, never dollar value. If a stock halves and the manager does nothing, the dollar value halves — that is the market moving, not a trade. Value change is still reported, just never used to classify.
Real output, Berkshire Q1 2026 vs Q4 2025:
| Action | Holding | Shares before → after | Δ |
|---|---|---|---|
| NEW | Delta Air Lines | 0 → 39,809,456 | +$2,646.5M |
| ADDED | Alphabet Class C | 17,846,142 → 54,249,798 | +204% |
| TRIMMED | Constellation Brands | 13,000,000 → 632,890 | −95.1% |
| TRIMMED | Nucor Corp | 6,407,749 → 3,907,075 | −39% |
Positions are matched on CUSIP, not issuer name — filers type names by hand
and they drift. Share classes are tracked separately, which is why Alphabet can
legitimately appear as NEW in one class and ADDED in another.
Input
{"ciks": ["1067983", "1350694"],"quarters": 4,"changesOnly": true,"minPositionValue": 10000000}
These are the manager's CIK, not the companies they hold. Berkshire
Hathaway is 1067983, Bridgewater 1350694, Renaissance Technologies
1037389.
| Field | Default | Notes |
|---|---|---|
ciks | ["1067983"] | Manager CIKs. |
quarters | 4 | Newest first. One extra is read as the comparison baseline. |
startPeriod / endPeriod | — | YYYY-MM-DD, quarter ends. |
changesOnly | false | Skip the holdings table, return only what moved. |
minPositionValue | — | Drop the long tail of tiny positions. |
trimThresholdPercent | 5 | Share-count move before ADDED / TRIMMED fires. |
includeAmendments | true | Prefer a 13F-HR/A over the original. |
contactEmail | — | Goes in the User-Agent, nowhere else. |
Output
portfolio — one row per quarter:
{"type": "portfolio","managerName": "Berkshire Hathaway Inc","periodOfReport": "2026-03-31","positions": 29,"rowsFiled": 90,"positionsWithSplitRows": 18,"totalValue": 263095703570,"reportedTotalValue": 263095703570,"totalsAgree": true,"largestHolding": "APPLE INC","largestHoldingPercent": 22.0,"concentrationHHI": 1185}
totalsAgree cross-checks the sum of the rows against the total the manager
reported on its own cover page. On the run above it reconciles exactly, which
is the strongest available proof that the units and aggregation are right.
change — one row per position that moved. holding — one row per
position per quarter, with weight, rank and implied price. quarter_changes
— the per-quarter headline.
Reliability
- Official SEC endpoints only:
data.sec.govandwww.sec.gov/Archives. No login, no session, no rendered-page scraping. - The information table has an arbitrary numeric filename (
53405.xmlon one filing,18337.xmlon another). It is discovered from the filing's ownindex.json, never guessed. - Runs under SEC's published 10 requests/second ceiling with a single serial
pacer, and sends a declared
User-Agentwith a contact address — SEC returns 403 to anything without one. - One unreadable quarter never fails the run; it lands in
RUN_SUMMARY.
Limits
- 13F covers US-listed equities, ADRs, certain convertibles and options. It does not cover cash, bonds, foreign listings or short positions. A 13F is not the whole portfolio and never was.
- Filings are due 45 days after quarter end, so the data is six weeks stale on arrival. That is the form, not the Actor.
- Filings before roughly 2013 are plain text with no XML table. Those are skipped with a recorded reason.
PRNrows are bond principal amounts, not share counts. They are kept separate and no per-share price is derived for them.- This is public regulatory data returned as filed. It is not investment advice and no forecast is implied by any field.
