3spread
All guides

Find every institution holding a stock (13F, in Python)

Use 13F filings to list the largest institutional positions in a security, ranked by dollar value, then drill into a single manager's filing history. Runs on a free API key.

The 3spread TeamJuly 14, 2026Institutional holdings dataset

Institutional investment managers with more than $100 million in qualifying assets have to disclose their equity positions every quarter on Form 13F. It is the closest thing there is to a public register of who owns what: the funds, the size of their stakes, and how those stakes change.

The catch is that 13F is filed per manager, not per security. If you want to know who owns a stock, you are implicitly asking to invert thousands of filings. This guide does that in one call, then drills into a single manager.

Everything below runs on the free Community tier: every dataset, 10,000 requests per day (600 per minute), no credit card.

Setup

pip install py3spread
export THREESPREAD_API_KEY="sk_live_..."

Who owns it, largest first

13F reports positions by CUSIP, so that is what we query on. iter_holdings streams across managers' filings, so a filter on CUSIP inverts the question for you: instead of one manager's book, you get one security's holders.

import itertools
from decimal import Decimal
from py3spread import Client
 
CUSIP = "037833100"  # Apple
 
with Client() as client:
    holdings = list(itertools.islice(
        client.institutional_holdings.iter_holdings(
            cusip=CUSIP,
            min_value=1_000_000_000,  # positions over $1B
            sort="value",
            order="desc",
        ),
        20,
    ))
 
    if not holdings:
        print("no holdings found")
        raise SystemExit
 
    print(f"largest reported positions in {holdings[0]['name_of_issuer']}:")
    for h in holdings:
        value = Decimal(h["value_usd"])
        shares = Decimal(h["ssh_prnamt"])
        print(
            f"  {h['filing_manager_name']:<45} ${value / 10**9:,.1f}B "
            f"({shares:,.0f} {h['ssh_prnamt_type']}, period {h['period_of_report']})"
        )

itertools.islice is doing real work here, and not only for tidiness. iter_holdings will keep paging for as long as you let it, and every page is a request against your daily budget. Slicing the iterator stops the pagination as soon as you have your twenty rows, instead of pulling thousands and throwing most of them away. Get in the habit: bound the iterator, filter server-side, and you will not notice the limits.

Two fields to understand before you trust the output. value_usd is the reported market value of the position, which is what you almost always want to sort on. ssh_prnamt is the share or principal amount, and ssh_prnamt_type tells you which of those it is, because 13F does not only cover common stock. Sorting on shares without checking the type is how you end up comparing a bond position to an equity one.

Drill into one manager

Once you have a manager, their filing history is one more call:

    manager = holdings[0]
    print(f"\nrecent 13F filings by {manager['filing_manager_name']}:")
 
    page = client.institutional_holdings.list(
        filing_manager_cik=manager["filing_manager_cik"], limit=5
    )
    for f in page["data"]:
        print(f"  {f['accepted_time']}  {f['form_type']}  period {f['period_of_report']}")

Note the two different time fields, because confusing them is the classic 13F mistake. period_of_report is the quarter the holdings describe. accepted_time is when the filing actually landed at the SEC, which can be up to 45 days later. If you are backtesting, accepted_time is the honest one: it is when you could have known.

Where to take it

Pull two consecutive quarters for the same manager and diff the holdings, and you have their trades: new positions, exits, adds, trims. That is the basis of every "what did the big funds buy last quarter" story, and it is a couple of dictionaries and a set difference away from the code above.

Widen it and you can measure crowding: for a given security, how concentrated is institutional ownership, and is it rising? A stock where the top five holders keep adding is a different setup from one being quietly distributed.

The dataset

Full endpoint reference and response schemas are on the 13F institutional holdings dataset page, and every parameter is in the interactive API reference.

Run this yourself

Everything here works on the free Community tier: every dataset, 10,000 requests per day (600 per minute), no credit card. Provision a key and paste the code in.