# ETF & Mutual Fund Holdings: Every Stock a Fund Owns (`scrapemint/fund-etf-holdings`) Actor

Keyless SEC NPORT-P data: give it a fund ticker such as VOO or ARKK and get every position it holds, with share count, dollar value and percent of portfolio, plus asset category and long or short. Quarterly filings, published about 60 days in arrears. Pay per row.

- **URL**: https://apify.com/scrapemint/fund-etf-holdings.md
- **Developed by:** [Ken M](https://apify.com/scrapemint) (community)
- **Categories:** Business, News
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$4.00 / 1,000 holding rows

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## ETF & Mutual Fund Holdings: Every Stock a Fund Owns

Keyless **SEC NPORT-P** data. No API key, no account.

Give it a fund ticker like `VOO` and it returns **what that fund actually holds**: every position, the share count, the dollar value, and what percent of the portfolio it represents.

> **Read this first: the data is quarterly and lags by roughly 60 days.** Funds file NPORT-P within 60 days of the period end, so a filing opened in late July reports positions as of 31 May. This is authoritative and complete, but it is not today's portfolio. Every row carries `reportPeriod` and `filedDate` so the age is never ambiguous.

- **Top** — the largest positions by percent of portfolio. The sensible default, since a total market index fund reports over 3,500 holdings.
- **Holdings** — the entire portfolio, every line.
- **Summary** — one row per fund: net assets, holding count, asset mix, long versus short, largest position and how concentrated the top ten are.

### Not the same as 13F

Our [SEC 13F Whale Tracker](https://apify.com/scrapemint/sec-13f-whale-tracker) covers **institutional managers** such as hedge funds, and 13F only lists US equities. **NPORT-P is filed by registered funds** — ETFs and mutual funds — and covers the **whole portfolio**, including bonds, short term investments and derivatives. Different filers, different form, different coverage.

### Who uses it

- **Investors comparing funds** — two S\&P trackers are not identical, and concentration and overlap are visible only at the holdings level.
- **Anyone checking exposure** — you own three funds and want to know how much of one company you really hold across all of them.
- **Advisers and research desks** — pull a peer group's portfolios into a spreadsheet without a data terminal.
- **Journalists and analysts** — "this fund put 8% into one name" is a story, and this is where the number lives.

### Input

| Field | Description |
|-------|-------------|
| `mode` | `top`, `holdings`, or `summary`. |
| `tickers` | Fund tickers, e.g. `VOO`, `QQQ`, `ARKK`. Max 25 per run. |
| `topN` | Positions per fund in top mode. The main cost lever. |
| `minPercent` | Skip positions below this share of the portfolio. |
| `assetCategory` | Filter to equities, debt, short term investments and so on. |
| `userAgent` | The SEC requires a contact email here. |
| `maxRows` | Row cap per run. |

### Output

- **Top and holdings**: `ticker`, `fundName`, `reportPeriod`, `filedDate`, `rank`, `securityName`, `title`, `cusip`, `isin`, `lei`, `shares`, `units`, `currency`, `valueUsd`, `percentOfPortfolio`, `position`, `assetCategory`, `assetCategoryLabel`, `issuerCategory`, `country`, `netAssetsUsd`, `filingUrl`.
- **Summary**: `ticker`, `fundName`, `seriesId`, `registrantName`, `reportPeriod`, `filedDate`, `totalAssetsUsd`, `netAssetsUsd`, `holdingsReported`, `holdingsAfterFilters`, `longPositions`, `shortPositions`, `topHolding`, `topHoldingPercent`, `topHoldingValueUsd`, `top10Percent`, `assetMixPercent`.

### Notes on the data

- **Only registered funds file this report.** An ordinary stock ticker will not resolve and returns a free note row rather than an error. Tickers are matched against the SEC's own fund symbol map, which carries about 28,000 entries.
- **A fund family files one report per fund series, several on the same day**, and the SEC's filing index does not say which is which. The right filing is found by matching the fund's series identifier, so asking for `VOO` gets the 500 Index Fund rather than whichever Vanguard filing happened to be first.
- **Asset categories are SEC codes**, mapped to readable labels: `EC` common equity, `DBT` debt, `STIV` short term investments, `EP` preferred, and so on. A single fund's portfolio routinely mixes several.
- **An asset mix can contain a small negative percentage.** Derivatives are reported with a negative weight when written rather than held, so a fund showing `derivative: -0.003` is not a data error.
- `percentOfPortfolio` is the fund's own reported weight, not a recomputed one, so it reconciles with the fund's published figures.
- Very large funds produce very many rows. A total stock market fund reports over 3,500 positions, so `top` mode with `topN` is the default for a reason.

### Pricing

Pay per event: **$0.004 per row**. The first 2 rows of every run are free.

Data source: SEC EDGAR NPORT-P filings and the SEC fund ticker map (`sec.gov`).

# Actor input Schema

## `mode` (type: `string`):

top = the largest positions by percent of portfolio. holdings = the entire portfolio, which for a total market fund is thousands of rows. summary = one row per fund with net assets, holding count, asset mix and largest position.

## `tickers` (type: `array`):

ETF or mutual fund ticker symbols, e.g. VOO, QQQ, ARKK, VTI. Maximum 25 per run. Ordinary stock tickers will not resolve, since only registered funds file this report.

## `topN` (type: `integer`):

How many of the largest positions to return for each fund. The main cost lever: a total market index fund reports over 3,500 holdings.

## `minPercent` (type: `number`):

Skip positions smaller than this share of the fund, e.g. 0.5 keeps only meaningful weights. 0 = keep everything.

## `assetCategory` (type: `string`):

Filter to one kind of holding. Funds report equities, debt, short term investments and derivatives in the same portfolio.

## `userAgent` (type: `string`):

The SEC requires a descriptive User-Agent containing a contact email, or it returns 403. Replace the default with your own name and email.

## `maxRows` (type: `integer`):

Cap on rows returned across all funds. Controls total cost.

## Actor input object example

```json
{
  "mode": "top",
  "tickers": [
    "VOO",
    "ARKK"
  ],
  "topN": 25,
  "minPercent": 0,
  "assetCategory": "all",
  "userAgent": "Scrapemint Research (admin@scrapemint.com)",
  "maxRows": 200
}
```

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "tickers": [
        "VOO",
        "ARKK"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapemint/fund-etf-holdings").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "tickers": [
        "VOO",
        "ARKK",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("scrapemint/fund-etf-holdings").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "tickers": [
    "VOO",
    "ARKK"
  ]
}' |
apify call scrapemint/fund-etf-holdings --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,scrapemint/fund-etf-holdings"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/lydvDlyJWTNgLCPGW/builds/oJcjtsWJzrfMvEGea/openapi.json
