Home / Guides / Ownership & holdings
Ownership & holdings

Read 13F cover pages and holdings together

Get a manager's Form 13F-HR cover page and its full information table from SecFeed, check the totals, and list the largest positions with portfolio weights.

A Form 13F-HR has two parts. The cover page (the primary XML document) names the manager, the report period, the report type and the summary totals: number of table entries and total value. The information table lists every position. Reading both lets you confirm that you have the whole portfolio before you analyze it.

SecFeed serves the two parts from two endpoints: /v1/form-13f for cover pages and /v1/form-13f/holdings for the information table rows.

Fetch the cover page and the holdings

This example uses Dodge & Cox (CIK 200217). fields=flat returns the curated cover fields without the full XML tree. The period parameter on the holdings endpoint uses the same MM-DD-YYYY format as the 13F cover page.

import os
from collections import defaultdict
import requests

BASE = "https://secfeedapi.com"
HEADERS = {"Authorization": f"Bearer {os.environ['SECFEED_KEY']}"}
CIK = 200217  # Dodge & Cox

r = requests.get(f"{BASE}/v1/form-13f", params={"cik": CIK, "fields": "flat"}, headers=HEADERS, timeout=120)
r.raise_for_status()
cover = r.json()["filings"][0]
flat = cover["flat"]
print(cover["formType"], "filed", cover["filedAt"], "|", flat["manager"])
print("Period:", flat["period"], "| report type:", flat["reportType"])
print(f"Entries: {flat['entries']:,.0f} | total value: ${flat['totalValue']:,.0f}")

r = requests.get(f"{BASE}/v1/form-13f/holdings", params={"cik": CIK, "period": flat["period"], "size": 1000},
                 headers=HEADERS, timeout=120)
r.raise_for_status()
rows = r.json()
total = sum(h["value"] for h in rows)
print(f"\nHoldings rows: {len(rows)} | sum of values: ${total:,.0f}")

positions = defaultdict(float)
for h in rows:
    positions[(h["issuer"], h["cusip"], h["put_call"] or "")] += h["value"]
print(f"\n{'Issuer':<32}{'CUSIP':<11}{'Value':>18}{'Weight':>8}")
for (issuer, cusip, pc), v in sorted(positions.items(), key=lambda x: -x[1])[:10]:
    print(f"{(issuer + (' ' + pc if pc else ''))[:31]:<32}{cusip:<11}{v:>18,.0f}{v / total:>8.1%}")

Output:

13F-HR filed 2026-08-13 | Dodge & Cox
Period: 06-30-2026 | report type: 13F HOLDINGS REPORT
Entries: 222 | total value: $191,008,088,994

Holdings rows: 222 | sum of values: $191,008,088,994

Issuer                          CUSIP                   Value  Weight
Johnson Controls International  G51502105       8,149,432,237    4.3%
The Charles Schwab Corp.        808513105       7,101,867,203    3.7%
RTX Corp.                       75513E101       6,662,036,733    3.5%
CVS Health Corp.                126650100       5,173,820,539    2.7%
Microsoft Corp.                 594918104       4,788,170,142    2.5%
Booking Holdings, Inc.          09857L108       4,551,705,968    2.4%
Humana, Inc.                    444859102       4,345,737,744    2.3%
Alphabet, Inc.                  02079K107       4,226,214,403    2.2%
MetLife, Inc.                   59156R108       4,097,759,602    2.1%
Sunbelt Rentals Holdings, Inc.  866966104       4,096,716,044    2.1%

Check the totals

The cover page reports 222 entries and a total of $191,008,088,994. The information table returned 222 rows that sum to exactly the same figure, so the holdings are complete. Run this check whenever you load a 13F: if a manager files a 13F-HR/A amendment that restates the table, or reports some positions confidentially, the counts will not match and you will know to look further.

Since January 2023 13F values are reported in whole dollars; earlier reports used thousands of dollars. Keep that in mind before comparing values across years.

Report types

The reportType field tells you what the filing contains:

  • 13F HOLDINGS REPORT: the manager reports all of its positions in this filing
  • 13F NOTICE: another manager reports the positions (the filer has an information table of zero rows)
  • 13F COMBINATION REPORT: some positions here, some reported by other managers

When you see a notice, the positions live in another manager's filing. The otherManagers count on the cover page tells you how many are involved.

Positions with puts and calls

The holdings rows include put_call. The example groups by issuer, CUSIP and put or call so that an option position never adds to a common stock position. For voting analysis, use vote_sole, vote_shared and vote_none on each row.

Next steps

More ownership & holdings guides

Run this guide with your own key

500 free API calls a month. Every example on this page works on the free plan.

Get free API key →