# Yahoo Finance Scraper (`mlg14/yahoo-finance-scraper`) Actor

Scrape Yahoo Finance ticker quotes, daily prices, dividends, splits, financial statements, news, analyst trends, holders, options, and earnings into one record per symbol.

- **URL**: https://apify.com/mlg14/yahoo-finance-scraper.md
- **Developed by:** [MLG Data](https://apify.com/mlg14) (community)
- **Categories:** Integrations, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.72 / 1,000 results

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/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

Scrape Yahoo Finance ticker quotes, daily stock prices, dividends, splits, financial statements, news, analyst ratings, institutional holders, options, and earnings. Export Yahoo Finance data to JSON, CSV, or Excel with one structured result for each ticker, providing a practical Yahoo Finance API alternative for public market data.

Give the scraper one or more symbols, choose a date window, and select the optional detail sections you need. Each completed ticker becomes one dataset item, so a portfolio of symbols can be joined, filtered, scheduled, or downloaded without combining separate runs.

### What data can you extract from Yahoo Finance?

The record has stable top-level keys. Values that do not apply to a security can be `null`, and optional collections can be empty. Prices and monetary amounts follow the security's reported `currency`; the scraper does not convert currencies.

| Field | Description | Example |
| --- | --- | --- |
| `ticker` | Requested symbol, normalized to uppercase | `AAPL` |
| `quoteUrl` | Public quote page | `https://finance.yahoo.com/quote/AAPL/` |
| `name` | Reported security name | A name supplied by the quote |
| `quoteType` | Instrument category | `EQUITY` |
| `exchange` | Reported exchange name | `NasdaqGS` |
| `currency` | Price currency | `USD` |
| `sector` | Reported business sector | `Technology` |
| `industry` | Reported industry | `Consumer Electronics` |
| `website` | Issuer website when published | An issuer URL |
| `description` | Public business summary | A text summary |
| `marketCap` | Market capitalization | `4999582056448` |
| `currentPrice` | Regular market price | `341.07` |
| `previousClose` | Previous regular session close | `335.92` |
| `change` | Price change from previous close | `5.14999` |
| `changePercent` | Price change in percentage points | `1.5331` |
| `priceTime` | Quote timestamp in UTC | An ISO timestamp |
| `open` | Regular session opening price | `336.04` |
| `dayHigh` | Regular session high | `341.67` |
| `dayLow` | Regular session low | `334.53` |
| `volume` | Regular session traded volume | `29649787` |
| `fiftyTwoWeekHigh` | 52-week high | `345.34` |
| `fiftyTwoWeekLow` | 52-week low | `243.42` |
| `trailingPE` | Trailing price-to-earnings ratio | `39.07` |
| `forwardPE` | Forward price-to-earnings ratio | `35.58` |
| `epsTrailing` | Trailing earnings per share | A numeric value |
| `epsForward` | Forward earnings per share | A numeric value |
| `dividendYield` | Annual yield in percentage points | `0.32` |
| `analystTargetPrice` | Mean analyst target price | `328.22` |
| `analystRecommendation` | Summary recommendation label | `buy` |
| `history` | Daily bars with date, open, high, low, close, adjusted close, and volume | An array of daily bars |
| `dividends` | Dividend date and amount within the history window | An array of events |
| `splits` | Split date and ratio within the history window | An array of events |
| `financials` | Annual and quarterly income, balance sheet, and cash flow periods | A structured object |
| `news` | Recent headline, link, publication time, and description | An array of articles |
| `recommendations` | Monthly analyst counts for strong buy through strong sell | An array of trends |
| `holders` | Institutional holders, fund holders, and ownership breakdown | A structured object |
| `options` | Listed expirations and nearest-expiry call and put contracts | A structured object |
| `earnings` | Next earnings date and recent quarterly actuals and estimates | A structured object |

A `history` entry contains `date`, `open`, `high`, `low`, `close`, `volume`, and `adjClose`. `dividends` entries contain `date` and `amount`; `splits` entries contain `date`, `numerator`, `denominator`, and `splitRatio`. The six statement arrays in `financials` are `annualIncome`, `quarterlyIncome`, `annualBalanceSheet`, `quarterlyBalanceSheet`, `annualCashFlow`, and `quarterlyCashFlow`. Each statement period includes an `endDate` and the numeric lines published for that period. Some statement sections are sparse because the public source omits individual lines.

Each `news` item contains `title`, `url`, `publishedAt`, and `description`. The `publishedAt` value follows the feed's published date format. The `recommendations` array has a `period` and counts under `strongBuy`, `buy`, `hold`, `sell`, and `strongSell`. The `holders` object has `institutional`, `funds`, and `breakdown`; each owner entry can have an organization, report date, position, value, ownership percentage, and change. The `options` object has `expirationDates`, `selectedExpiration`, `calls`, and `puts`. Contract records contain symbol, strike, last price, bid, ask, volume, open interest, implied volatility, moneyness, and last trade time. `earnings` has `nextEarningsDate` and `quarterly`, where quarters can include actual, estimate, difference, and surprise percentage.

### How to scrape Yahoo Finance

1. Enter ticker symbols in `tickers`. Use the exact market symbol shown in the public quote URL, including exchange suffixes when needed.
2. Set `start_date` and `end_date` if you need a specific daily history window. Both endpoints are inclusive in the resulting daily bars.
3. Select the detail sections. Statements and news are enabled by default; holders and options can be enabled for deeper company records.
4. Run the actor. It emits one result per valid ticker for which a quote or price history is available.
5. Open the dataset to inspect records or export them as JSON, CSV, or Excel.

Symbols are deduplicated within a run. The scraper processes a symbol once even if it appears repeatedly in the input. To keep a large portfolio manageable, split its symbols into batches and schedule the batches independently.

### Input

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `tickers` | String array | Required | Symbols to collect, such as `AAPL`, `MSFT`, or `GOOG`. |
| `start_date` | Date string | One year ago | First date in the daily price window, in `YYYY-MM-DD` format. |
| `end_date` | Date string | Today | Last date in the daily price window, in `YYYY-MM-DD` format. |
| `includeFinancials` | Boolean | `true` | Include annual and quarterly statement data. |
| `includeNews` | Boolean | `true` | Include recent public headlines. |
| `maxNewsPerTicker` | Integer | `10` | Maximum number of headline items per symbol; zero returns none. |
| `includeHolders` | Boolean | `false` | Include publicly reported institutional and fund owners. |
| `includeOptions` | Boolean | `false` | Include expiration dates and the nearest listed option chain. |
| `maxItems` | Integer | `0` | Maximum ticker records for the run; zero means all input symbols. |
| `proxyConfiguration` | Object | Proxy enabled | Proxy settings for public requests. |

Example input for a compact price and fundamentals collection:

```json
{
  "tickers": ["AAPL", "MSFT", "GOOG"],
  "start_date": "2026-08-01",
  "end_date": "2026-09-25",
  "includeFinancials": true,
  "includeNews": true,
  "maxNewsPerTicker": 3,
  "includeHolders": false,
  "includeOptions": false
}
```

The actor validates dates before making requests. If only one date is supplied, the missing boundary defaults to a one-year start or today's end, respectively. `end_date` must not precede `start_date`. Daily history uses a one-day interval; changing the date window does not change the snapshot quote, analyst data, statements, or recent news attached to the record.

### Output example

The following abbreviated item illustrates the dataset structure. Prices, ratings, news, and market dates change as the source updates.

```json
{
  "ticker": "AAPL",
  "quoteUrl": "https://finance.yahoo.com/quote/AAPL/",
  "quoteType": "EQUITY",
  "currency": "USD",
  "marketCap": 4977636933632,
  "currentPrice": 341.07,
  "previousClose": 335.92,
  "changePercent": 1.5331,
  "history": [
    {
      "date": "2026-09-25",
      "open": 336.0400085449219,
      "high": 341.6700134277344,
      "low": 334.5299987792969,
      "close": 341.07000732421875,
      "volume": 29950100,
      "adjClose": 341.07000732421875
    }
  ],
  "dividends": [{"date": "2026-08-10", "amount": 0.27}],
  "splits": [],
  "financials": {
    "annualIncome": [
      {"endDate": 1759190400, "totalRevenue": 416161000000, "netIncome": 112010000000}
    ]
  },
  "news": [{"publishedAt": "Sat, 26 Sep 2026 07:12:45 +0000"}],
  "recommendations": [
    {"period": "0m", "strongBuy": 6, "buy": 19, "hold": 13, "sell": 3, "strongSell": 3}
  ],
  "options": {
    "selectedExpiration": "2026-09-28",
    "calls": [
      {"contractSymbol": "AAPL260928C00250000", "strike": 250, "lastPrice": 89.85, "openInterest": 1}
    ]
  },
  "earnings": {
    "nextEarningsDate": "2026-10-29",
    "quarterly": [{"date": "2Q2026", "actual": 2.02, "estimate": 1.89243}]
  }
}
```

This example is shortened to show the relationships between fields. Actual dataset items retain all available daily bars, statement periods, news items, and optional sections selected in the input. When an optional section is disabled, `financials`, `holders`, or `options` is `null`, while disabled news is an empty array. When a section is enabled but unavailable from the public source, the same empty or null shape indicates no data was collected for that section.

### Use cases

- **Portfolio monitoring:** Collect current prices, daily changes, volume, and market capitalization for a watchlist in one run. The symbol remains attached to every result, making it easy to compare or alert on movements.
- **Historical price analysis:** Download daily OHLCV bars with adjusted close values for a defined time window. Dividend and split events in that same window help explain discontinuities in raw close prices.
- **Fundamental research:** Review annual and quarterly statement values alongside valuation ratios and analyst targets. Keep each security's currency with the record before comparing values across markets.
- **Earnings preparation:** Combine the expected earnings date, recent earnings actuals and estimates, and current analyst rating distribution in one ticker record.
- **Ownership review:** Enable the holder section to inspect reported institutional positions, fund ownership, and the broad insider and institutional ownership breakdown.
- **Options watchlists:** Enable the option section to obtain available expiration dates and the nearest expiry's current call and put contracts. This is suited to watching one listed chain per ticker rather than downloading every contract across every expiry.

### How much does it cost to scrape Yahoo Finance?

The listed result price is **$0.72 per 1,000 ticker records**, or $0.00072 for each delivered result. A record is one ticker, even when its `history` array contains many daily bars. The maximum item setting limits delivered records and the associated result charge. Check the run's cost display for the final amount and any account-specific usage details.

| Records delivered | Result charge |
| ---: | ---: |
| 30 | $0.0216 |
| 1,000 | $0.72 |
| 5,000 | $3.60 |

For example, a run with 30 valid symbols costs about two cents in result charges. A daily portfolio of 1,000 symbols costs $0.72 each day, or about $21.60 for 30 such runs, assuming every symbol produces a record. Five 1,000-symbol batches produce 5,000 records and $3.60 in result charges. A run with invalid or unavailable symbols can produce fewer items than input symbols; only delivered results count toward this calculation. Enabling optional sections changes the work needed for a ticker but does not change the number of result items it represents.

### Tips for best results

Use exact symbols from public quote URLs. Some non-US securities require a suffix, while indices and funds use their own symbol conventions. Symbols are case-normalized, but punctuation is preserved. Start with a short ticker list to confirm that the public source exposes the sections you care about for that instrument type.

Keep history windows as narrow as your analysis allows. The default is one year of daily bars, which already gives enough observations for common trend and volatility work. Longer windows increase each output item's size. If you only need a current snapshot, you can set a recent start and end date while retaining the quote, fundamentals, and other current sections.

Disable `includeFinancials`, `includeNews`, `includeHolders`, or `includeOptions` when a workflow does not need them. This reduces requests and makes runs faster. For broad watchlists, consider collecting quotes, history, and news routinely, then running a smaller detailed list for statements, owners, and option chains. Use `maxNewsPerTicker` to cap headline volume; news can change rapidly and is not tied to the historical price date window.

Review the `currency`, `exchange`, and `quoteType` before aggregating records. Market capitalization, prices, option strikes, and financial statement values can use different currencies across symbols. The scraper reports values as published and does not convert or reconcile accounting conventions. For repeat collections, retain the run time with your exported dataset because the price snapshot and public finance pages can update after a run completes.

### Limits

The source is public market data, so availability differs by ticker and instrument. A company equity can have sector, financial statements, analyst trends, holders, and listed options; an index, currency pair, or fund may have only quote and history. A valid ticker can also omit a field or have a delayed market quote. A missing value appears as `null`, and a missing collection is empty or `null` according to its field type.

Direct anonymous access to some finance endpoints can be rejected. This actor reads the structured data already supplied to public quote pages for those sections. If a public page changes structure or becomes unavailable, its section may be empty until the actor is updated. History comes from a separate public chart endpoint, so a ticker can still have history even if some profile or analyst fields are unavailable.

The `options` section covers the nearest expiry returned by the public options page. It lists the other expiration dates so you can see what is available, but it does not fetch every expiry's contracts. Financial statements include the periods and numeric line items present in the public page response. Some statement lines are absent or zero in the source, and the scraper does not infer missing accounting values. The news section reflects recent feed items, which can include articles from third-party publishers and may be empty for thinly covered tickers.

Large historical windows make a single ticker item much larger. If you plan to export CSV, nested arrays are serialized within the ticker row; JSON is usually easier for detailed histories and statements. There is no intraday history setting in this actor. Dates refer to UTC calendar boundaries used for daily chart requests, and the source's exchange calendar determines which trading days appear.

### Automation examples

- “Collect daily prices and analyst recommendations for these 20 ticker symbols, then flag any symbol with a price change above 3%.”
- “Fetch the latest annual statement periods and the nearest options chain for this watchlist; save one JSON item per symbol.”

The input names and output fields are stable, so scheduled jobs and downstream workflows can reuse the same configuration. A record is self-contained for a ticker: its quote URL, currency, history window, earnings, and optional sections travel together.

### FAQ

#### Is it legal to collect these records?

This actor reads publicly accessible market pages and a public news feed. You are responsible for using the data in line with the source's terms, applicable market-data restrictions, and local law. News content can carry publisher rights. Do not treat the output as licensed redistribution rights or investment advice.

#### Do I need to configure proxies?

The default input enables a proxy. The actor begins with a datacenter route and can escalate when public pages block requests. You can change proxy settings in the input if your account and use case require it. Availability can vary by region and over time.

#### How fast is a run?

Runtime depends mainly on the number of tickers, which optional sections are enabled, and how the public pages respond. A compact quote and history run uses fewer requests than a run that also fetches statements, news, holders, and options. For large lists, use smaller scheduled batches and watch completion times in your account.

#### Can I schedule or monitor collections?

Yes. Save a tested input, schedule it at the cadence that suits your use case, and inspect the run status and dataset. Regular runs produce fresh snapshots; they do not update historical records in earlier datasets. Use a persistent destination if you want to build a longitudinal database.

#### Can I export to spreadsheets?

The dataset supports JSON, CSV, and Excel downloads. JSON preserves the nested historical bars and detail sections. For a flat spreadsheet, select the top-level quote columns or transform nested arrays into separate sheets after export.

#### Why is a field empty?

The instrument may not have that field, the public page may omit it, or an optional section may be disabled. Check `quoteType` and the relevant input switch first. For example, a symbol without listed options will not have call and put contracts even when `includeOptions` is enabled.

#### Does the date range filter news or fundamentals?

No. `start_date` and `end_date` apply to daily price history and its dividend and split events. Quotes, fundamentals, analyst ratings, holders, option chains, and headlines are current public data available at run time.

### Integrations

Use the run API, dataset exports, schedules, and webhooks to feed recurring market workflows. Dataset items can be sent to a spreadsheet, a database, a notification system, or an automation platform. Preserve the `ticker` and `currency` keys when joining records with another source, and store the run time when comparing snapshots across days.

### Support

Open an issue on the Issues tab; we reply within 24h and add fields on request.

# Actor input Schema

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

Yahoo Finance ticker symbols. Each symbol produces one dataset item.

## `start_date` (type: `string`):

First calendar date to include in daily price history (YYYY-MM-DD). Defaults to one year ago.

## `end_date` (type: `string`):

Last calendar date to include in daily price history (YYYY-MM-DD), inclusive. Defaults to today.

## `includeFinancials` (type: `boolean`):

Fetch annual and quarterly income, balance sheet, and cash flow summaries.

## `includeNews` (type: `boolean`):

Fetch recent ticker headlines from the public finance news feed.

## `maxNewsPerTicker` (type: `integer`):

Maximum recent news items saved for each ticker.

## `includeHolders` (type: `boolean`):

Fetch public institutional and fund holdings plus ownership summary.

## `includeOptions` (type: `boolean`):

Fetch expiration dates and calls and puts for the nearest expiry.

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

Stop after this many ticker records across the run. Zero means all supplied tickers.

## `proxyConfiguration` (type: `object`):

Proxy settings for fetching public pages and endpoints.

## Actor input object example

```json
{
  "tickers": [
    "AAPL",
    "MSFT",
    "GOOG"
  ],
  "includeFinancials": true,
  "includeNews": true,
  "maxNewsPerTicker": 10,
  "includeHolders": false,
  "includeOptions": false,
  "maxItems": 0,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

One structured record per valid ticker in the default dataset.

# 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",
        "GOOG"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("mlg14/yahoo-finance-scraper").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",
        "GOOG",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("mlg14/yahoo-finance-scraper").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",
    "GOOG"
  ]
}' |
apify call mlg14/yahoo-finance-scraper --silent --output-dataset

```

## MCP server setup

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

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/WC8yi4QvJMRQb2Nnz/builds/GxcZvufjbCd0XezYf/openapi.json
