# Yahoo Finance Price History — Stocks, ETFs, Crypto, FX (`northbell/yahoo-finance-price-history`) Actor

Daily and intraday prices for stocks, ETFs, crypto and FX from Yahoo Finance. One row per symbol with last price, day change, period return, volatility and max drawdown, or one row per bar. Dividends and splits optional. Rank change since your last run. No login.

- **URL**: https://apify.com/northbell/yahoo-finance-price-history.md
- **Developed by:** [Northbell](https://apify.com/northbell) (community)
- **Categories:** Business, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.60 / 1,000 symbol summaries

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Yahoo Finance Price History — Stocks, ETFs, Crypto, FX

Give it a list of Yahoo Finance symbols — stocks (`AAPL`), ETFs (`SPY`), crypto (`BTC-USD`), currency pairs (`EURUSD=X`), indices (`^GSPC`), futures (`GC=F`) — and get one clean row per symbol with the numbers you would work out anyway: **last price, day change, return over the period, annualised volatility and maximum drawdown**. Or switch to one row per bar (open, high, low, close, adjusted close, volume), with dividends and splits if you want them. **$2 per 1,000 symbols** (bars are **$0.10 per 1,000**), no login, no API key, no cookie or crumb to look after.

Run it again — or put it on a schedule — and every symbol row also tells you **what changed since the last run**: the symbol's **rank** by return among your list (1 = best), `previousRank`, `rankChange` (positive = moved up), whether it is new on the list, and the price move since then. Yahoo only shows you today; this keeps your leaderboard.

### What you get

Summary rows (`type: "summary"`, the default output):

| Field | What it is |
|---|---|
| `symbol`, `name`, `currency`, `exchange`, `instrumentType`, `timezone`, `url` | the instrument (`EQUITY`, `ETF`, `CRYPTOCURRENCY`, `CURRENCY`, `INDEX`, `FUTURE`, `MUTUALFUND`…) and where its dates are counted |
| `lastPrice`, `previousClose`, `change`, `changePct` | Yahoo's latest price, the previous regular session's close, and the move between them |
| `periodReturnPct`, `totalReturnPct` | return over the range, in percent: from the close just before the range starts to the latest close (price only), and the same with dividends reinvested (`totalReturnPct`) |
| `periodHigh`, `periodLow`, `avgVolume` | highest high and lowest low in the range, and the average volume per bar |
| `volatility` | annualised volatility in percent: standard deviation of the log returns between bars × √252 for daily bars (√365 for crypto; √52, √12 or √4 for weekly, monthly or quarterly bars) |
| `maxDrawdownPct` | the deepest fall from a running peak to a later close, in percent (negative; 0 if it never fell) |
| `fiftyTwoWeekHigh`, `fiftyTwoWeekLow` | Yahoo's 52-week range |
| `range`, `interval`, `bars`, `firstDate`, `lastDate`, `marketTime` | what was read: range asked for, bar size Yahoo returned, number of bars, first and last bar date (exchange-local), time of the latest price |
| `dividendCount`, `dividendsPerShare`, `splitCount` | only when *Include dividends and splits* is on |
| `rank`, `previousRank`, `rankChange`, `isNew`, `previousRunAt`, `previousLastPrice`, `changeSinceLastRunPct` | your list ranked by `periodReturnPct` (1 = best), and the change since the previous run with the same range and bar size (all `null` on the first run) |

Bar rows (`type: "bar"`, when *Output* is `bars`): `symbol`, `date` (exchange-local), `time` (UTC), `open`, `high`, `low`, `close`, `adjClose`, `volume`.
Dividend rows (`type: "dividend"`): `symbol`, `date`, `amount`, `currency`. Split rows (`type: "split"`): `symbol`, `date`, `numerator`, `denominator`, `ratio` (e.g. `10:1`).

### Use it for

- **Watchlists and screening** — one row per symbol with return, volatility and drawdown side by side; sort a whole index or portfolio in a spreadsheet
- **Backtests and models** — every daily, weekly or intraday bar for any range, with adjusted close, dividends and splits
- **Daily monitoring** — schedule it and see who moved up the leaderboard since yesterday
- **Dashboards and agents** — clean JSON that a BI tool or an AI agent can read without parsing Yahoo's chart format

### Input

```json
{ "symbols": ["AAPL", "MSFT", "BTC-USD", "EURUSD=X", "^GSPC"], "range": "1y", "interval": "1d", "output": "summary", "includeDividends": false }
```

`range` is one of `1d 5d 1mo 3mo 6mo 1y 2y 5y 10y ytd max`; `interval` (bar size) is one of `1m 2m 5m 15m 30m 60m 90m 1h 4h 1d 5d 1wk 1mo 3mo`. Yahoo limits intraday bars: `1m` reaches back 8 days; `2m`, `5m`, `15m`, `30m` and `90m` 60 days; `60m`, `1h` and `4h` 730 days (the Actor tells you before it starts if a combination is not served). `range: "max"` returns the whole history at the bar size you chose.

The leaderboard is remembered in a named key-value store in your Apify account, one snapshot per range and bar size (it keeps up to 2,000 symbols), so the second run of the same Actor already shows the changes.

### Pricing

**$2 per 1,000 symbol summaries** and **$0.10 per 1,000 bars**, plus $0.01 per run. Dividend and split rows are billed like bars. Error rows (unknown symbols) are free. The $0.01 run-start fee is the one charge every run pays, even one that returns nothing.

Examples: 100 symbols as summaries cost $0.21. A year of daily bars for 10 symbols is about 2,500 bars: $0.26. Forty years of daily bars for one large stock is about 10,000 bars: $1.01.

### Notes

- **Not investment advice.** Yahoo's data is delayed on many exchanges (often by 15 minutes or more) and is provided by Yahoo for information only. It can contain gaps and errors. Do not trade on it without checking it against your broker or exchange.
- Public data only: the same chart data Yahoo shows on its quote pages, no login. Nothing about you or other people is collected.
- The last bar can be the current session, still trading, so `lastPrice` and the last bar change during market hours. Dates are the exchange's local calendar dates.
- `periodReturnPct` is measured the way Yahoo's own charts do it: from the **close just before the range starts** to the latest close, so `5d` is five trading days, `ytd` is the move since last year's final close, `1d` is the day's change, and the figure is the same whatever bar size you pick. For `max` there is no start, so it runs from the first bar's close; if Yahoo's start value is missing it falls back to the first bar (its open for intraday bars and for a single bar). `totalReturnPct` starts at the same point and reinvests the dividends paid inside the range.
- `volatility` and `maxDrawdownPct` are measured on the bars you chose. `volatility` needs at least 3 daily closes, so it is `null` for a single day; intraday bars are reduced to each day's last close first.
- `previousClose`, `change` and `changePct` are Yahoo's day change: the latest regular price against the previous regular session's close (after-hours trading is not counted), the same figures Yahoo shows on its quote page. Crypto and FX trade around the clock, so there Yahoo's "previous close" is its end-of-day mark and can differ slightly from the previous bar's close.
- Yahoo sometimes sends the newest daily bar of a stock without its close (seen in the hours around midnight UTC). The Actor then uses Yahoo's latest regular price as that bar's close, so `lastDate` and the return reach today. A day Yahoo skipped entirely (it happens now and then with crypto right after midnight UTC) stays out, so `bars` can be one lower than the number of days.
- Weekly, monthly and quarterly series from Yahoo end with an extra bar that holds only the latest session. The Actor folds it into the current week, month or quarter (earlier open, wider high and low, latest close, volumes added), so you get one bar per period. Yahoo's own `5d` bars are returned as they come, and their last bar can be the current session alone.
- Fields that are only filled in some cases: `totalReturnPct` and `adjClose` need daily or longer bars (`null` for intraday); `avgVolume` is `null` for instruments Yahoo reports no volume for (currency pairs, mutual funds, some indices such as `^VIX`); `dividendCount`, `dividendsPerShare` and `splitCount` appear only with *Include dividends and splits*; the six since-last-run fields are `null` on the first run for a given range and bar size, and `previousRank`/`rankChange` are `null` for a symbol that was not in the previous run (`isNew` is `true`).
- Ranks are among the symbols of that run. Every symbol keeps the rank and price of the last run it was in, so you can run several watchlists with the same range and bar size; but if you add or remove symbols between runs, a rank change partly reflects the new list. `changeSinceLastRunPct` is always the plain price move.
- A symbol Yahoo does not know (typo, delisted, wrong suffix) gives a free error row with Yahoo's reason. If Yahoo cannot be reached at all, the run fails instead of returning an empty dataset. Busy or rate-limited responses are retried twice.
- Up to 500 symbols per run. Use Yahoo's ticker format: `BRK-B` (not `BRK.B`), `^GSPC`, `EURUSD=X`, `7203.T`, `0700.HK`, `M&M.NS`.

To pull macro data by country (GDP, inflation, population), see [World Bank Data Scraper](https://apify.com/northbell/world-bank-data-scraper).

### For AI agents

`{"symbols": ["AAPL", "BTC-USD"], "range": "1y"}` returns two `summary` rows with last price, day change, one-year return, volatility and max drawdown. `{"symbols": ["AAPL"], "range": "5d", "output": "bars"}` returns the five daily bars. Rows have `type`: `summary`, `bar`, `dividend`, `split` or `error`.

# Actor input Schema

## `symbols` (type: `array`):

One Yahoo Finance ticker per line (commas also work): AAPL, BRK-B, ^GSPC (index), EURUSD=X (currency pair), BTC-USD (crypto), GC=F (futures), 7203.T (Tokyo). A finance.yahoo.com/quote/… link works too. Up to 500 per run.

## `range` (type: `string`):

How far back to read: 1d, 5d, 1mo, 3mo, 6mo, 1y, 2y, 5y, 10y, ytd (since 1 January) or max (the whole history). Intraday intervals are limited by Yahoo: 1m reaches back 8 days, 5m 60 days, 1h 730 days.

## `interval` (type: `string`):

The size of one bar: 1d is a daily bar. 1wk, 1mo and 3mo give weekly, monthly and quarterly bars. 1m to 4h are intraday bars (limited range, see Range). Returns, volatility and drawdown are measured on these bars.

## `output` (type: `string`):

summary gives one row per symbol with the figures worked out (last price, day change, period return, volatility, max drawdown and the change since your last run). bars gives one row per price bar (open, high, low, close, adjusted close, volume).

## `includeDividends` (type: `boolean`):

Add one row per dividend and per stock split in the range, and dividend and split counts to the summary rows. Billed at the bar price.

## Actor input object example

```json
{
  "symbols": [
    "AAPL",
    "MSFT",
    "BTC-USD"
  ],
  "range": "1mo",
  "interval": "1d",
  "output": "summary",
  "includeDividends": false
}
```

# Actor output Schema

## `symbols` (type: `string`):

Last price, day change, period return, volatility, max drawdown and the rank change since the last run.

## `bars` (type: `string`):

One row per price bar (open, high, low, close, adjusted close, volume) when Output is bars.

# 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 = {
    "symbols": [
        "AAPL",
        "MSFT",
        "BTC-USD"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("northbell/yahoo-finance-price-history").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 = { "symbols": [
        "AAPL",
        "MSFT",
        "BTC-USD",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("northbell/yahoo-finance-price-history").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 '{
  "symbols": [
    "AAPL",
    "MSFT",
    "BTC-USD"
  ]
}' |
apify call northbell/yahoo-finance-price-history --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,northbell/yahoo-finance-price-history"
        }
    }
}
```

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/nYWanCJTfPEJgFNtz/builds/kPBrCOMiPRctea5Re/openapi.json
