# Yahoo Finance Scraper (quotes, key stats, history, alerts) (`datahamster/yahoo-finance-quotes`) Actor

One row per ticker: live quote, key stats (P/E, EPS, dividend yield, 52-week range, market cap) and optional daily price history, read from Yahoo Finance without login. Monitor mode alerts on price and volume changes for a watchlist you choose.

- **URL**: https://apify.com/datahamster/yahoo-finance-quotes.md
- **Developed by:** [Viktor Dubnytskiy](https://apify.com/datahamster) (community)
- **Categories:** Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.80 / 1,000 result items

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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 Scraper (quotes, key stats, history, alerts)

One row per ticker — a live quote, key statistics and (optionally) daily price history — read from `finance.yahoo.com/quote/<TICKER>/` without logging in. Works for stocks, ETFs and crypto pairs (e.g. `AAPL`, `SPY`, `BTC-USD`).

### What you get

Real rows from the example dataset (`tickers: ["AAPL", "MSFT"]`):

| symbol | name | price | change / changePercent | marketState |
|---|---|---|---|---|
| `AAPL` | Apple Inc. | `338.98` | `+2.85` / `+0.85%` | `POST` |
| `MSFT` | Microsoft Corporation | `501.61` | `+7.83` / `+1.59%` | `POST` |

Full row (quote): `id`/`symbol`, `url`, `type`, `name`, `exchange`, `currency`, `price`, `change`, `changePercent`, `previousClose`, `open`, `dayLow`, `dayHigh`, `volume`, `avgVolume`, `marketCap`, `peRatio`, `eps`, `dividendYield`, `fiftyTwoWeekLow`, `fiftyTwoWeekHigh`, `marketState`, `quotedAt`, `query`, `scrapedAt`. History rows (`includeHistory: true`) add `date`, `high`, `low`, `close`, `adjClose` in place of the quote-only fields.

An unknown ticker is simply skipped (Yahoo's own "no such symbol" answer) — it does not fail the run or get charged.

### Use cases

- Build a watchlist dashboard from a flat list of tickers without scraping HTML yourself.
- Pull key statistics (P/E, EPS, dividend yield, market cap) for a screener or a portfolio report.
- Monitor mode alerts your webhook or Telegram chat when a ticker's price or volume changes since the last check.

### Try it in 10 seconds

Hit **Start**/**Try it** — the input already works: `tickers: ["AAPL", "MSFT"]`, `includeHistory: false`, `maxItems: 100`, nothing required.

To watch a ticker list for price/volume moves: save the task, set **Mode** to `monitor`, and put it on a schedule (Apify → Schedules → cron `*/30 9-16 * * 1-5` every 30 minutes on weekday market hours). Each run then alerts your webhook or Telegram chat only on price/volume changes since the previous check.

### How it works

1. Each ticker's quote page is read as a logged-out visitor; the quote and key-stats fields come out of the JSON Yahoo's own page already embeds for itself, not from scraping visible text.
2. With `includeHistory` on, the ticker's history page for the requested window is read the same way and turned into one row per trading day.
3. An unknown ticker (Yahoo redirects it to Symbol Lookup) is skipped, not charged, and does not fail the run. A page that comes back as neither a quote nor a lookup answer is treated as a block and retried on a higher proxy tier before the run gives up.

### Input

| Field | Meaning | Default |
|---|---|---|
| `tickers` | Ticker symbols to look up, e.g. `AAPL`, `MSFT`, `SPY`, `BTC-USD` | `["AAPL", "MSFT"]` |
| `includeHistory` | Also return daily price history rows | `false` |
| `historyDays` | Days of history to cover when `includeHistory` is on | `30` |
| `maxItems` | Stop after this many rows (quote + history combined) | `100` |
| `mode` | `scrape` or `monitor` (only new/changed since last run) | `scrape` |
| `monitorStateId`, `webhookUrl`, `telegramBotToken`, `telegramChatId` | Monitor-mode state key and alert targets | empty |

### Pricing

| Event | Price |
|---|---|
| result | $0.001 per row ($1 per 1,000) |
| monitor-check | $0.005 per monitor run |
| change | $0.001 per new/changed row |

Charged only for rows actually pushed. A quote row and each history row are each one result.

### Why this actor

- No login, no API key, no crumb/session to manage.
- Quotes and key statistics in one row — no second lookup for P/E, EPS or dividend yield.
- Monitor mode with webhook and Telegram alerts on price and volume changes.
- A run that finds nothing pushes nothing and charges no result events; `RUN_SUMMARY` in the run's key-value store explains why.

### Limits

- Quotes are the delayed quote Yahoo serves logged-out visitors, not a real-time feed.
- No analyst names, no article authors, no forum/community content — only the ticker's own market data.
- `historyDays` beyond what Yahoo's own chart returns for the ticker (e.g. a very young listing) simply yields fewer rows.

### FAQ

**Does it need a Yahoo account or API key?** No. Every request is made as a logged-out visitor; there is no field for credentials at all.

**What happens for a ticker that doesn't exist?** It is skipped — no row, no charge — and does not fail the run. Everything else in the same run still comes back.

**Is any of this person-level data?** No. Rows are market data for the ticker itself (price, stats, history). No analyst names or article authors are collected.

### Changelog

- 0.1: initial release — quotes, key statistics, optional price history, monitor mode.

***

If this actor saved you time, a short review on its Store page genuinely helps other people find it. Found a bug or need a field that is missing? Open a ticket on the **Issues** tab.

# Actor input Schema

## `maxItems` (type: `integer`):

Stop after this many results (you are charged only for pushed items)

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

scrape = full results; monitor = only new/changed items since the previous run of this task

## `monitorStateId` (type: `string`):

Optional state id when not running as a saved task (monitor mode)

## `webhookUrl` (type: `string`):

POST a change summary here in monitor mode

## `telegramBotToken` (type: `string`):

Optional: bot token for monitor-mode change summaries

## `telegramChatId` (type: `string`):

Optional: chat id that receives monitor-mode summaries

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

Ticker symbols to look up, one per line, e.g. "AAPL", "MSFT", "SPY" (ETF), "BTC-USD" (crypto pair). Case-insensitive; duplicates are requested once.

## `includeHistory` (type: `boolean`):

true = also return one row per trading day (open/high/low/close/adjusted close/volume) for the last `Price history days`, per ticker. false = quote rows only. Example: false.

## `historyDays` (type: `integer`):

How many calendar days back the price history covers when `Include price history` is on, e.g. 30. Non-trading days (weekends, holidays) are not counted as rows.

## Actor input object example

```json
{
  "maxItems": 100,
  "mode": "scrape",
  "tickers": [
    "AAPL",
    "MSFT"
  ],
  "includeHistory": false,
  "historyDays": 30
}
```

# Actor output Schema

## `results` (type: `string`):

All pushed rows (dataset, JSON)

## `resultsTable` (type: `string`):

Dataset in the Console viewer

## `runSummary` (type: `string`):

RUN\_SUMMARY record

# 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": [
        "AAPL",
        "MSFT"
    ],
    "historyDays": 30
};

// Run the Actor and wait for it to finish
const run = await client.actor("datahamster/yahoo-finance-quotes").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": [
        "AAPL",
        "MSFT",
    ],
    "historyDays": 30,
}

# Run the Actor and wait for it to finish
run = client.actor("datahamster/yahoo-finance-quotes").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": [
    "AAPL",
    "MSFT"
  ],
  "historyDays": 30
}' |
apify call datahamster/yahoo-finance-quotes --silent --output-dataset

```

## MCP server setup

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

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/QTxSQt1TA6BgbeZiw/builds/WmcnvpERQosCeBjTd/openapi.json
