# ETF API -  Data with Holdings, Returns & Sectors (`giovannibiancia/etf-api`) Actor

Real-time API access to 3,500+ European ETFs via Apify Standby Mode.
Get TER, fund size, returns (1M to max), top 10 holdings with weights,
sector and country breakdown per ETF. Pass an ISIN and get instant
structured data. Perfect for fintech, robo-advisors and portfolio tools.

- **URL**: https://apify.com/giovannibiancia/etf-api.md
- **Developed by:** [Giovanni Bianciardi](https://apify.com/giovannibiancia) (community)
- **Categories:**
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $10.00 / 1,000 etf items

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#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 Data API — Real-Time ETF & Fund Data

**Query thousands of ETFs and funds instantly — no scraping, no waiting for a run to finish.** This Actor keeps a live, always-fresh catalogue of ETF/ETP data (ISIN, price, TER, returns, risk, holdings, and more) and serves it back to you as a simple REST API, in milliseconds.

### 💡 Before you use this API

<p align="center">
  <a href="https://bananalitycs.com/datasets?utm_actor=just-etf-api" target="_blank">
    <img src="https://bananalitycs.com/banana_thinking.png" width="180"/>
  </a>
</p>

<p align="center">
  Some datasets like this one are already available <strong>ready-to-use</strong> on
  <a href="https://bananalitycs.com/datasets?utm_actor=just-etf-api"><strong>bananalitycs.com</strong></a> — download instantly or request custom delivery.
</p>

<p align="center">
  <a href="https://bananalitycs.com/datasets?utm_actor=just-etf-api" target="_blank">
    <img src="https://img.shields.io/badge/🗂️%20Browse%20Datasets-bananalitycs.com-4CAF50?style=for-the-badge"/>
  </a>
  &nbsp;
  <a href="https://bananalitycs.com/done-for-you?utm_actor=just-etf-api" target="_blank">
    <img src="https://img.shields.io/badge/🤝%20Done%20For%20You-Custom%20Delivery-6C63FF?style=for-the-badge"/>
  </a>
</p>

### 🚀 Why use this API?

**For Fintech Developers:** Drop ETF data straight into your app with a single HTTP call — no scraper to run, no dataset to download and refresh yourself.

**For Financial Advisors & Wealth Managers:** Look up or screen funds by TER, returns, or asset allocation on demand, right from a spreadsheet macro, a script, or a no-code tool.

**For Researchers & Analysts:** Pull the exact slice of the catalogue you need — one ISIN, a filtered list, or a sorted top-N — instead of a full dataset dump.

Unlike a typical scraper, this Actor never needs to be "run and waited on": it stays online and answers queries in real time.

### 🛠️ How to use it

#### Step 1: Start the Actor in Standby mode

Open this Actor in Apify Console and hit **Start**. It doesn't scrape anything on start — it just comes online and starts serving the ETF catalogue. Once it's running, open the **Standby** tab to find its API URL and try requests right from the browser.

#### Step 2: Call your API URL

Every Standby Actor gets a stable URL:

```
https://<actor-name>.<your-username>.apify.actor
```

#### Step 3: Authenticate

Requests need your Apify API token, either as a header:

```
Authorization: Bearer <APIFY_TOKEN>
```

or as a query parameter:

```
?token=<APIFY_TOKEN>
```

#### Example request

```bash
curl "https://<actor-name>.<your-username>.apify.actor/etfs?q=msci%20world&limit=5" \
  -H "Authorization: Bearer <APIFY_TOKEN>"
```

### 🔎 What you can search for

| You want to...                              | Use this                          | Example                                      |
| -------------------------------------------- | ---------------------------------- | --------------------------------------------- |
| Look up one fund                             | `GET /etfs/{isin}`                 | `/etfs/IE00B5BMR087`                          |
| Search by name or ISIN                       | `q`                                 | `q=s&p 500`                                   |
| Get several funds at once                    | `isin` (comma-separated)           | `isin=IE00B5BMR087,BG9000011163`              |
| Filter by whether the fund is still active   | `active`                            | `active=true`                                 |
| Filter by income policy                      | `distribution_policy`              | `distribution_policy=Accumulating`            |
| Filter by replication method                 | `replication_method`               | `replication_method=Full replication`         |
| Filter by fund type                          | `entity_type`                      | `entity_type=ETF`                             |
| Filter by any numeric range (fees, returns…) | `min_<field>` / `max_<field>`      | `min_ter_pct=0&max_ter_pct=0.5`               |
| Sort the results                             | `sort` (prefix `-` for descending) | `sort=-return_1y_pct`                         |
| Page through results                         | `limit` (1–100) / `offset`         | `limit=20&offset=40`                          |

More examples:

```
GET /etfs?q=msci world&active=true&sort=-fund_size_mln&limit=10
GET /etfs?min_ter_pct=0&max_ter_pct=0.2&replication_method=Full replication
GET /etfs?distribution_policy=Distributing&min_return_1y_pct=10
```

### 📤 What you get back

Each fund comes back as a rich JSON record:

| Category                  | Fields                                                                                     |
| -------------------------- | -------------------------------------------------------------------------------------------- |
| Identification             | ISIN, name, entity type, active/inactive, profile URL                                       |
| Characteristics            | Fund size, TER (total expense ratio), distribution policy, replication method                |
| Price                      | Latest quote, previous quote, first/latest quote date                                        |
| Performance                | Returns over 1M, 3M, 6M, YTD, 1Y, 3Y, 5Y, since launch, plus each recent calendar year        |
| Portfolio composition      | Top 10 holdings, country allocation, sector allocation (each with name and weight %)          |

Every request returns only the fields available for that fund — no boilerplate, no need to parse an HTML page yourself.

#### Example: a single fund lookup

```json
GET /etfs/IE00B5BMR087
```

```json
{
  "isin": "IE00B5BMR087",
  "name": "iShares Core S&P 500 UCITS ETF USD (Acc)",
  "entity_type": "ETF",
  "active": true,
  "distribution_policy": "Accumulating",
  "replication_method": "Physical Full",
  "fund_size_mln": 114133,
  "ter_pct": 0.07,
  "latest_quote": 627.29,
  "latest_quote_date": "2026-03-13",
  "return_1y_pct": 14.41,
  "return_3y_pct": 65.24,
  "return_5y_pct": 87.01,
  "top_holdings_0_name": "NVIDIA Corp.",
  "top_holdings_0_weight_pct": 7.38,
  "countries_0_name": "United States",
  "countries_0_weight_pct": 95.21,
  "sectors_0_name": "Information Technology",
  "sectors_0_weight_pct": 34.83,
  "url": "https://www.justetf.com/it/etf-profile.html?isin=IE00B5BMR087"
}
```

#### Example: a filtered list

```json
GET /etfs?q=msci world&sort=-fund_size_mln&limit=2
```

```json
{
  "total": 3,
  "count": 2,
  "limit": 2,
  "offset": 0,
  "billed_items": 2,
  "is_free_tier": false,
  "free_tier_remaining": null,
  "items": [
    { "isin": "IE00B4L5Y983", "name": "iShares Core MSCI World UCITS ETF", "fund_size_mln": 98234, "ter_pct": 0.2 },
    { "isin": "IE00BK5BQT80", "name": "Vanguard FTSE All-World UCITS ETF", "fund_size_mln": 24211, "ter_pct": 0.22 }
  ]
}
```

### 💰 Pricing

This Actor uses **Pay-Per-Event** billing: you're only charged for the fund records you actually receive, one small charge per record — not per API call, and never for a `404` or an empty result.

- **Try it for free:** every caller gets a small free preview (the first 20 ETF records) with no budget required.
- **Beyond that:** allocate a Pay-Per-Event budget for the run to keep querying. Once exhausted, requests return `402 Payment Required` until you top up.
- A single call can never return more than 100 records, so a request is always billed for exactly what it returns — no surprises.

Check `GET /health` any time to see how many free records you have left and whether the catalogue is up to date.

### 🎯 Use cases

- **Portfolio dashboards** — look up live fund data (fees, returns, holdings) as users add ETFs to a portfolio.
- **Robo-advisors & screening tools** — filter and sort the catalogue by TER, returns, or asset class to power recommendations.
- **Client reporting** — pull current fund metrics on demand instead of maintaining your own scraper.
- **Research & backtesting** — fetch exactly the funds and fields you need, without downloading the entire catalogue.

### 🧑‍💻 For developers

The Actor also ships interactive API docs, generated from the same OpenAPI 3.1 schema used by the Standby tab in Apify Console:

- `GET /docs` — Swagger UI
- `GET /redoc` — ReDoc
- `GET /openapi.json` — raw schema

If you're contributing to this Actor and change a route or field in `src/api.py` / `src/models.py`, regenerate the static schema before deploying:

```bash
python scripts/generate_openapi.py
```

# Actor input Schema

## `refresh_interval_secs` (type: `integer`):

How often the API reloads data from the dataset in the background, without restarting.

## `free_tier_max_results` (type: `integer`):

How many ETF records a caller with no Pay-Per-Event budget allocated can receive in total from this run before being asked to allocate a budget.

## Actor input object example

```json
{
  "refresh_interval_secs": 300,
  "free_tier_max_results": 20
}
```

# Actor output Schema

## `api` (type: `string`):

No description

## `apiDocs` (type: `string`):

No description

# 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 = {
    "refresh_interval_secs": 300,
    "free_tier_max_results": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("giovannibiancia/etf-api").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 = {
    "refresh_interval_secs": 300,
    "free_tier_max_results": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("giovannibiancia/etf-api").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 '{
  "refresh_interval_secs": 300,
  "free_tier_max_results": 20
}' |
apify call giovannibiancia/etf-api --silent --output-dataset

```

## MCP server setup

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

```

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/eJmEpmmfsWWXtsk8d/builds/0VOLaPLRnqMgvOq28/openapi.json
