ETF Holdings Tracker — Daily Constituents & Weights API
Pricing
from $100.00 / 1,000 etf holding records
ETF Holdings Tracker — Daily Constituents & Weights API
Track the top holdings and weights of US-listed ETFs — parsed from public ETF pages into source-linked JSON for analysts, funds and AI agents. No API key. Pay per record.
Pricing
from $100.00 / 1,000 etf holding records
Rating
0.0
(0)
Developer
NexGenData
Maintained by CommunityActor stats
0
Bookmarked
7
Total users
0
Monthly active users
2 days ago
Last modified
Categories
Share
ETF Holdings Tracker
ETF holdings and ETF constituents, with weights, for US-listed ETFs.
Track ETF constituents and weights, parsed into clean JSON. Built for analysts, funds, fintech builders and AI agents. Factual public market data — not financial or investment advice.
📊 Sample Output

etf_name | etf_issuer | etf_aum_billion_usd | etf_aum_usd | holding_name | holding_sector |
|---|---|---|---|---|---|
| State Street SPDR S&P 500 ETF | State Street | 803.33 | 803330000000 | NVIDIA Corporation | Technology |
| State Street SPDR S&P 500 ETF | State Street | 803.33 | 803330000000 | Apple Inc. | Technology |
| State Street SPDR S&P 500 ETF | State Street | 803.33 | 803330000000 | Microsoft Corporation | Technology |
| State Street SPDR S&P 500 ETF | State Street | 803.33 | 803330000000 | Amazon.com, Inc. | Consumer Discretionary |
| State Street SPDR S&P 500 ETF | State Street | 803.33 | 803330000000 | Alphabet Inc. | Communication Services |
| State Street SPDR S&P 500 ETF | State Street | 803.33 | 803330000000 | Broadcom Inc. | Technology |
Real rows from run 2YboMYBuLqcD8NUgA on build 0.0.16 (2026-09-25), unedited apart from masked emails/phones and shortened long text; fields the source does not publish are empty.
⚙️ Sample inputs
This is the Store example input — the same input Apify's automated check runs — so it is proven to return rows on the current build. Paste it into the input form, or send it through the API, CLI or a schedule:
{"etf_symbols": ["SPY","QQQ","VTI"],"limit": 1000,"max_holdings_per_etf": 100,"min_weight_pct": 0,"country": "all","issuer": "all"}
🔧 Input reference
| Field | Type | Default | What it does |
|---|---|---|---|
etf_symbols | array | ["SPY", "QQQ", "VTI"] | US-listed ETF tickers to pull holdings for. Defaults to SPY, QQQ and VTI when left empty, so a run with no input still returns rows. Each ETF is fetched independently and emits on… |
limit | integer | 1000 | Hard cap on total holding records emitted across every ETF requested. Set to 0 to disable the cap. This caps the dataset AFTER per-ETF max_holdings_per_etf has been applied — use… |
max_holdings_per_etf | integer | 25 | Cap on constituents returned per ETF. Use 10 for top-10 sampling, 0 for everything the source returns. The source currently returns at most 25 per ETF, so values above 25 have no… |
min_weight_pct | number | 0 | Filter out holdings below this weight threshold (in percent of ETF AUM). Use 0.5 to keep only positions above 0.5% of AUM, 0 for everything. |
country | string (all, United States, China, Japan, United Kingdom, Canada, Germany, France, …) | "all" | Filter holdings by inferred country of incorporation. 'all' returns everything. Country is inferred from the holding's ticker and legal-entity name, not read from a filing. |
issuer | string (all, iShares, Vanguard, State Street, Invesco, ARK, JPMorgan, Schwab, …) | "all" | Filter the requested ETFs by sponsor. 'all' returns every issuer. Issuer is inferred from the ETF's name. |
monitor_new_only | boolean | false | Optional monitor mode. When true (and monitor_key set), emit only holdings not seen in prior runs of the same monitor_key — captures additions/changes on a schedule. Default off =… |
monitor_key | string | A unique label for your scheduled watch. State is isolated per key so schedules never share a seen-set. Required for monitor mode. |
🧾 JSON sample record
One real record from run 2YboMYBuLqcD8NUgA (emails/phones masked, long text shortened):
{"etf_symbol": "SPY","etf_name": "State Street SPDR S&P 500 ETF","etf_issuer": "State Street","etf_aum_billion_usd": 803.33,"etf_aum_usd": 803330000000,"holding_symbol": "NVDA","holding_name": "NVIDIA Corporation","holding_sector": "Technology","weight_pct": 8.22,"shares_held": 298385133,"market_value_usd": 66033726000,"holding_country": "United States","as_of_date": "2026-09-25","etf_holdings_url": "https://stockanalysis.com/etf/spy/holdings/","data_source": "stockanalysis.com"}
💰 Pricing
| Event | Price (USD) | When it is charged |
|---|---|---|
Actor Start (apify-actor-start) | $0.01 | Charged when the Actor starts running. Number of events charged depends on Actor memory (one event per GB, minimum one event). |
ETF holding record (apify-default-dataset-item) | $0.1 | Charged per ETF holding returned with symbol, weight, shares, market value, sector, and country exposure. |
Pay-per-event: you pay only for what the run delivers. A run that delivers nothing bills no result events (only the actor-start event, when the actor defines one). Example: a run that delivers 100 results costs 100 × $0.1 = $10.00 plus the start fee.
🗂 Where the data comes from
Holdings, weights, share counts and fund-level assets are parsed from the public ETF pages on stockanalysis.com (https://stockanalysis.com/etf/{ticker}/holdings/ and /etf/{ticker}/). Every record carries that source URL in etf_holdings_url and "data_source": "stockanalysis.com".
This Actor does not read SEC EDGAR, N-PORT or 13F filings, and records do not carry sec.gov links. For filing-derived holdings see the related SEC actors below.
Coverage limit you should know about before you run it. The source's free holdings page currently returns only the top 25 constituents by weight per ETF and states the rest are behind its subscription (for example "Showing 25 of 505 holdings" for SPY, 25 of 105 for QQQ, 25 of 47 for ARKK). This Actor returns what the source returns, reports the truncation in the run status message and in the OUTPUT record, and never fabricates the missing constituents.
📊 What you get
Clean JSON, one record per holding (15 fields):
etf_symbol,etf_name,etf_issuer,etf_aum_usd,etf_aum_billion_usdholding_symbol,holding_name,weight_pct,shares_heldmarket_value_usd— computed as ETF AUM × weight %holding_sector,holding_country— inferred from the ticker and company name, not read from a filingas_of_date,etf_holdings_url,data_source
💵 Pricing
- Actor start: $0.01 per event (one event per GB of run memory, minimum one)
- Result: $0.10 per holding record — about 10 records per $1
One charge per record delivered:
- No
etf_symbolsgiven → the run uses the default tickers SPY, QQQ and VTI (the same three the Console form prefills) and bills only the records it delivers. - A ticker the source doesn't cover (HTTP 404) → no records, no charge; it is named in the status message.
- Source blocked, non-200, or the holdings table missing → three attempts with a fresh residential proxy session each time; if no ETF yielded anything, the run fails with a status message naming the cause instead of finishing green and empty.
- Run time limit → the Actor stops cleanly, says "stopped early at the run time limit", and bills only the records already delivered.
- Charge limit → delivery stops the moment the run's charge limit is reached; a record is never delivered without its charge.
🤖 Use with AI agents
Structured, source-linked data for LLM and agent pipelines — point Claude, the OpenAI Agents SDK, an n8n flow or any MCP-aware client at it.
Sample agent prompt:
List the top 20 holdings and weights for an ETF as JSON.
Agentic payments (x402): Supports agentic payment via x402 — agents can call this actor with USDC, no API key required.
Run it on a schedule
ETF top holdings and weights shift with prices every trading day, while actual changes to which stocks a fund holds happen less often. A daily run after the market close suits weight tracking, and a weekly run is enough if you only care about positions entering the top holdings. Between runs, existing holdings come back with updated weight_pct, shares_held and market_value_usd, and new names can appear. Turn on monitor mode with monitor_new_only: true and a unique monitor_key, and each scheduled run returns only holdings not seen in earlier runs for that key, so you are billed only for those. Send each run's results onward with a webhook, Google Sheets, Zapier, Make or the Apify API.
Video guides from Apify: Schedule your Actor · Integrations
FAQ
Why use this instead of the ETF issuer's website?
Each issuer publishes holdings in its own format on its own site. This actor pulls holdings for many US-listed ETFs in one run and returns them in one clean JSON format: fund name, issuer and assets, plus each holding's symbol, name, weight, shares, market value, sector and country. It needs no API key, can filter by weight, issuer and country, and has a monitor mode for scheduled runs. The data is parsed from the public ETF pages on stockanalysis.com, and every record links to its source page. It is not affiliated with any ETF issuer.
What does a typical run cost?
You pay per result, not for run time: $0.10 for each row in the results, plus $0.01 per run start (charged per GB of run memory, minimum one). A run that returns 25 ETF holdings costs about $2.51. Live prices are always shown in the Pricing tab.
How do I download the holdings of SPY, QQQ or VTI as CSV?
Put the tickers in etf_symbols, for example SPY, QQQ and VTI, and run it. Each holding becomes one row, which you can export as CSV, JSON or Excel. Use min_weight_pct to drop small positions, for example 0.5 to keep only holdings above 0.5% of the fund.
Does it return every holding in an ETF?
No. The source page currently shows only the top 25 holdings by weight for each ETF, so the actor returns at most 25 per fund (for example 25 of about 505 for SPY). It reports this cut-off in the run's status message and never makes up the missing holdings.
Does this data come from SEC filings?
No. It does not read SEC EDGAR, N-PORT or 13F filings, and records do not carry sec.gov links. holding_sector and holding_country are inferred from the ticker and company name, and market_value_usd is calculated as fund assets times weight. For filing-based fund holdings, use an N-PORT or 13F actor.
What happens if I ask for an ETF the source does not cover?
That ticker returns no records and no charge, and it is named in the run's status message.
Related actors
- Fund Portfolio & Security Ownership Lookup — SEC N-PORT API — full fund holdings from SEC N-PORT filings.
- SEC Fund Holdings Monitor — N-PORT Filing Tracker API — watch new N-PORT holdings filings as they land.
- SEC Form 13F Tracker Pro — Institutional Holdings API — see what institutional managers hold.
- SEC 13F Holdings Delta Tracker — Quarter-Over-Quarter — track quarter-over-quarter changes in institutional positions.
- Finviz Stock Screener — US Market Data API — screen the stocks that show up in your ETFs.