# Yahoo Finance Scraper: Quotes, History, Financials (`automation_craft/yahoo-finance-scraper`) Actor

Scrape Yahoo Finance for any ticker list, no login or API key: stocks, ETFs, funds, indices, currencies, crypto. Quotes with the exchange delay, daily or intraday history, annual and quarterly statements, analyst targets, news, options, screeners. Pay per row, JSON or CSV; misses are free.

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

## Pricing

from $0.32 / 1,000 quotes

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 Scraper: Quotes, History, Financials

**Yahoo Finance Scraper** turns a list of ticker symbols into Yahoo Finance data rows: the quote with the exchange delay, daily or intraday price history, annual and quarterly financial statements, the company or fund profile, analyst data, news headlines and option chains, plus Yahoo's predefined screeners. No Yahoo login, no API key and no proxy setting. You pick the data types; each one is a separate row per ticker and is charged only when Yahoo has data of that kind. A ticker Yahoo does not know, or a data type it has nothing for, comes back as a free status row that says why.

It works for stocks on US and other exchanges, ETFs, mutual funds, indices (`^GSPC`), currencies (`EURUSD=X`), crypto (`BTC-USD`) and futures (`ES=F`). Use it as a Yahoo Finance API for your own code (curl, Node and Python examples below), as a scheduled feed for a dashboard, or as a CSV export: history and news can come as one flat row per candle or per headline.

#### Why this one

- **Pay only for data that came back.** Unknown tickers, data types Yahoo has nothing for, blocked requests and invalid input values are free status rows. A symbol is charged one Quote per run, even when it is in your list and in a screener, or in two screeners.
- **The delay on every quote.** Each Quote row carries Yahoo's own `exchangeDataDelayedBy` (minutes), `quoteSourceName` and `marketState`, so you can see which prices are delayed.
- **Quarterly statements you can choose.** Income statement, balance sheet and cash flow, each with annual, quarterly and trailing twelve month periods, under Yahoo's own line names.
- **News from two Yahoo routes.** Yahoo's search route and its RSS headline feed are merged by article id, so non US tickers, which the search route leaves empty, still get headlines from the feed.
- **Nested or flat.** Price history and news come as one record per ticker (cheapest) or as one row per candle or headline (for spreadsheets).
- **Fast.** A one ticker quote run took about 2 seconds on the platform.

### Quick start

1. Put ticker symbols into **Tickers**, one per line, exactly as Yahoo Finance shows them: `AAPL`, `BRK-B`, `^GSPC`, `EURUSD=X`, `BTC-USD`, `ES=F`, `0700.HK`, `RELIANCE.NS`. Lower case, a leading `$` (`$aapl`) and a pasted `https://finance.yahoo.com/quote/AAPL/` link work too, and one line may hold several symbols separated by commas.
2. Pick the **Data types** you want. The default is Quote only.
3. Optional: set the price history range and interval, the statements and periods, the number of headlines or option expiries, or pick screeners.
4. Click **Start**. Rows appear in the Dataset tab; export JSON, CSV or Excel, or read them through the API.

### What you get

Every row has a `type`: `quote`, `history`, `candle`, `financials`, `profile`, `analyst`, `news`, `article`, `options`, `status` or `summary`. Data rows repeat the identity fields `symbol` and `name` (most also `quoteType`, `exchange` and `currency`), so a CSV row stands on its own, and end with `scrapedAt`.

| Data type | Row `type` | What one row holds | Event |
|---|---|---|---|
| quote | `quote` | One ticker's quote, flat, Yahoo's own field names | Quote |
| history | `history` (nested) or `candle` (flat) | Candles with dividends and splits, or one candle per row | Ticker record, or Candle per row |
| financials | `financials` | Every selected statement and period of one ticker | Ticker record |
| profile | `profile` | Company or fund profile, key statistics, holders, filings | Ticker record |
| analyst | `analyst` | Targets, recommendations, estimates, earnings history, rating changes, Yahoo insights | Ticker record |
| news | `news` (nested) or `article` (flat) | Latest headlines, or one headline per row | Ticker record, or News article per row |
| options | `options` | The chain of one expiry, calls and puts | Ticker record per expiry |
| screeners | `quote` | One screener row, plus `screener`, `screenerTitle`, `screenerRank` | Quote |

#### Quote row

One row per ticker. It leads with `symbol`, `name`, `shortName`, `quoteType`, `exchange`, `exchangeCode`, `currency`, `marketState`, `quoteSourceName`, `exchangeDataDelayedBy`, `regularMarketPrice`, `regularMarketChange`, `regularMarketChangePercent`, `regularMarketTime` and `position` (where the ticker sits in your list, zero based), then every other field Yahoo's quote carries for that instrument under Yahoo's own name: day and 52 week ranges, volume and average volume, bid and ask, the post market price, market cap, shares outstanding, trailing and forward P/E, EPS, book value, price to book, dividend rate and yield, the 50 and 200 day averages, earnings dates, the analyst rating, and fund, crypto or futures fields where they apply. Unix times become ISO dates, and `firstTradeDate` closes the row. A stock row carried 70 to 91 fields in our test runs, an index or currency 55.

Fill rates measured on 300 mixed symbols sent to Yahoo's quote endpoint on 2026-10-01 (294 came back, 117 distinct fields in all; US markets were closed at the time, which is why pre and post market fields look the way they do). They are what Yahoo publishes for each asset class, not a choice of the Actor:

| Field | US stocks (151) | Other markets (50) | ETFs (25) | Mutual funds (10) | Indices (15) | Currencies (14) | Crypto (15) | Futures (10) |
|---|---|---|---|---|---|---|---|---|
| `regularMarketPrice` | 100% | 98% | 100% | 100% | 100% | 100% | 100% | 100% |
| `regularMarketVolume` | 100% | 98% | 100% | 0% | 86.7% | 100% | 100% | 100% |
| `marketCap` | 99.3% | 92% | 0% | 0% | 0% | 0% | 100% | 0% |
| `trailingPE` | 77.5% | 88% | 72% | 70% | 0% | 0% | 0% | 0% |
| `forwardPE` | 100% | 92% | 4% | 0% | 0% | 0% | 0% | 0% |
| `epsTrailingTwelveMonths` | 100% | 92% | 80% | 70% | 0% | 0% | 0% | 0% |
| `dividendYield` | 49% | 96% | 100% | 100% | 0% | 0% | 0% | 0% |
| `averageAnalystRating` | 94.7% | 98% | 0% | 0% | 0% | 0% | 0% | 0% |
| `sharesOutstanding` | 99.3% | 92% | 40% | 40% | 0% | 0% | 0% | 0% |
| `earningsTimestamp` | 98.7% | 86% | 0% | 0% | 0% | 0% | 0% | 0% |
| `bid`, `ask` | 100% | 96% | 100% | 0% | 86.7% | 100% | 0% | 100% |
| `postMarketPrice` | 97.4% | 0% | 100% | 0% | 0% | 0% | 0% | 0% |
| `exchangeDataDelayedBy` | 100% | 98% | 100% | 100% | 100% | 100% | 100% | 100% |
| `quoteSourceName` | 99.3% | 98% | 100% | 100% | 93.3% | 100% | 100% | 100% |
| `marketState` | 100% | 98% | 100% | 100% | 100% | 100% | 100% | 100% |
| `currency` | 100% | 98% | 100% | 100% | 93.3% | 100% | 100% | 100% |
| `netAssets`, `netExpenseRatio`, `ytdReturn` | 0% | 0% | 100% | 100% | 0% | 0% | 0% | 0% |
| `circulatingSupply` | 0% | 0% | 0% | 0% | 0% | 0% | 100% | 0% |
| `openInterest`, `expireDate` | 0% | 0% | 0% | 0% | 0% | 0% | 0% | 100% |

`exchangeDataDelayedBy` in the same sample: 0 minutes for the US exchanges, currencies and crypto; 15 for London, XETRA, Paris, Hong Kong, NSE, BSE, Sao Paulo and Milan and most Toronto rows; 20 for Tokyo, Osaka, ASX, Korea and Taiwan; 10 for the CME group futures.

Example Quote row (platform run of the prefill input on 2026-10-01; shortened: 26 of its 84 fields):

```json
{
  "type": "quote",
  "symbol": "AAPL",
  "name": "Apple Inc.",
  "quoteType": "EQUITY",
  "exchange": "NasdaqGS",
  "exchangeCode": "NMS",
  "currency": "USD",
  "marketState": "PREPRE",
  "quoteSourceName": "Nasdaq Real Time Price",
  "exchangeDataDelayedBy": 0,
  "regularMarketPrice": 333.02,
  "regularMarketChange": 3.62,
  "regularMarketChangePercent": 1.09897,
  "regularMarketTime": "2026-09-30T20:00:01.000Z",
  "position": 0,
  "regularMarketVolume": 49875295,
  "fiftyTwoWeekLow": 243.42,
  "fiftyTwoWeekHigh": 345.34,
  "postMarketPrice": 334.25,
  "trailingPE": 37.714607,
  "forwardPE": 34.7426,
  "dividendYield": 0.33,
  "marketCap": 4860153954304,
  "averageAnalystRating": "2.2 - Buy",
  "firstTradeDate": "1980-12-12T14:30:00.000Z",
  "scrapedAt": "2026-10-01T04:39:50.134Z"
}
```

#### Price history: `history` record or `candle` rows

Nested (`historyOutput` `nested`, the default): one `history` record per ticker with `interval`, `range`, `start`, `end`, `exchangeTimezone`, `firstTradeDate`, `regularMarketPrice`, `regularMarketTime`, `fiftyTwoWeekHigh`, `fiftyTwoWeekLow`, `chartPreviousClose`, `candleCount`, `firstCandleAt`, `lastCandleAt`, `emptySlotsSkipped`, `outsideWindowSkipped`, `liveRow`, and the lists `candles` (`timestamp`, `date`, `open`, `high`, `low`, `close`, `adjClose`, `volume`), `dividends` (`timestamp`, `date`, `amount`), `splits` (`timestamp`, `date`, `numerator`, `denominator`, `ratio`) and `capitalGains`. One Ticker record per ticker, however many candles.

Flat (`historyOutput` `rows`): one `candle` row per candle with `symbol`, `name`, `exchange`, `currency`, `interval`, `timestamp`, `date`, `open`, `high`, `low`, `close`, `adjClose`, `volume`, `liveRow`, `scrapedAt`. Dividends and splits are in the nested record only.

A slot without a close (a holiday in a currency pair, a session that has only just opened) is skipped and counted in `emptySlotsSkipped`, never delivered as a candle. `adjClose` exists for daily and longer intervals only. `date` is the trading day in the exchange's own time zone. With `historyStart` or `historyEnd`, only candles of those days are delivered: a row Yahoo returns for a day outside them (a currency pair's bar for the next day starts at 23:00 UTC) is dropped and counted in `outsideWindowSkipped`, never charged.

`liveRow`: after the candles of the interval you asked for, Yahoo adds one more row for the latest trade or session (a monthly series ends with September's candle and then a row for September 30; a 5 minute series ends with a row at the second of the last trade). That row is not a candle of your interval, so it is never counted or charged as one. You still get it: as `liveRow` (`timestamp`, `date`, `open`, `high`, `low`, `close`, `volume`) on the history record, and on the last candle row when candles come as rows (`null` on every other row). On the daily interval the row is today's candle and is delivered as one, once per trading day.

Example candle row (platform run, AAPL, 1 month of daily candles):

```json
{
  "type": "candle",
  "symbol": "AAPL",
  "name": "Apple Inc.",
  "exchange": "NasdaqGS",
  "currency": "USD",
  "interval": "1d",
  "timestamp": "2026-09-01T13:30:00.000Z",
  "date": "2026-09-01",
  "open": 316.9800109863281,
  "high": 327.29998779296875,
  "low": 314.7300109863281,
  "close": 325.1300048828125,
  "adjClose": 325.1300048828125,
  "volume": 53167400,
  "liveRow": null,
  "scrapedAt": "2026-10-01T16:16:37.610Z"
}
```

#### Financial statements: `financials` record

One record per ticker with `currency`, `statements` (which of income, balance, cashflow came back), `annualPeriods`, `quarterlyPeriods`, `trailingPeriods`, `lineItems`, `latestAnnual`, `latestQuarter`, and the lists `annual`, `quarterly` and `trailing`. Each period carries `asOfDate`, `periodType` (`12M`, `3M` or `TTM`), `currency`, and the objects `incomeStatement`, `balanceSheet` and `cashFlow`, whose keys are Yahoo's own line names (`TotalRevenue`, `GrossProfit`, `OperatingIncome`, `EBITDA`, `NetIncome`, `DilutedEPS`, `TotalAssets`, `TotalDebt`, `StockholdersEquity`, `OperatingCashFlow`, `FreeCashFlow`, `CapitalExpenditure` and the rest of the 375 line names the Actor asks for). Lines Yahoo leaves empty are left out.

Example (platform run, AAPL; shortened to one quarterly period and five lines per statement):

```json
{
  "type": "financials",
  "symbol": "AAPL",
  "name": "Apple Inc.",
  "currency": "USD",
  "statements": ["income", "balance", "cashflow"],
  "annualPeriods": 4,
  "quarterlyPeriods": 6,
  "trailingPeriods": 0,
  "lineItems": 163,
  "latestAnnual": "2025-09-30",
  "latestQuarter": "2026-06-30",
  "quarterly": [
    {
      "asOfDate": "2026-06-30",
      "periodType": "3M",
      "currency": "USD",
      "incomeStatement": { "TotalRevenue": 109417000000, "GrossProfit": 54770000000, "OperatingIncome": 35695000000, "NetIncome": 29789000000, "DilutedEPS": 2.02 },
      "balanceSheet": { "TotalAssets": 383266000000, "TotalDebt": 84344000000, "StockholdersEquity": 107520000000, "CashAndCashEquivalents": 39544000000 },
      "cashFlow": { "OperatingCashFlow": 34369000000, "FreeCashFlow": 31914000000, "CapitalExpenditure": -2455000000 }
    }
  ]
}
```

#### Profile: `profile` record

`sector`, `industry`, `website`, `country`, `city`, `state`, `address`, `zip`, `phone`, `fullTimeEmployees`, `longBusinessSummary`, `irWebsite`, `sectorKey`, `industryKey`, `companyOfficers` (name, title, age, pay where Yahoo has it), `governance` (Yahoo's audit, board, compensation and shareholder rights risk scores), `keyStatistics`, `summaryDetail`, `financialData`, `holders` (`breakdown`, `institutions`, `funds`, `insiders`, `insiderTransactions`, `netSharePurchaseActivity`), `fund` (`profile`, `topHoldings`, `performance` for ETFs and mutual funds), `indexComponents` (an index that lists its members), `futuresChain` (a futures root), `secFilings` (the latest 25) and `secFilingsTotal`. A stock gets the company fields, an ETF or fund the fund fields, a future its chain; an index or a currency usually has no profile and gets a free `no_data` status instead.

#### Analyst: `analyst` record

`currentPrice`, `targetHighPrice`, `targetLowPrice`, `targetMeanPrice`, `targetMedianPrice`, `recommendationMean`, `recommendationKey`, `numberOfAnalystOpinions`, `recommendationTrend` (strong buy to strong sell counts by month), `earningsEstimates` (EPS and revenue estimates, EPS trend and revisions per period), `earningsHistory` (actual against estimate, surprise), `ratingChanges` (the latest 100 upgrades and downgrades with firm, grades and price targets) and `ratingChangesTotal`, `calendarEvents` (next earnings date, ex-dividend and dividend dates), `earnings`, `indexTrend`, and `insights` (Yahoo's technical outlook, key technical levels, valuation note, third party recommendation, company snapshot scores and up to 10 research report summaries with `reportsTotal`), with `insightsRead` saying whether the insights call answered (when it did not, the record is delivered without them and the ticker's status row says so). Example values for MSFT on 2026-10-01: `targetMeanPrice` 578.41516, `recommendationKey` `strong_buy`, `numberOfAnalystOpinions` 52, `ratingChangesTotal` 936.

#### News: `news` record or `article` rows

Nested (`newsOutput` `nested`, the default): one `news` record per ticker with `articleCount`, `latestArticleAt`, `routes` (how many articles each of the two Yahoo routes returned; `null` for a route that could not be read), `allRoutesRead` and `articles`. When one route could not be read, the articles of the other are delivered and the ticker's status row says that its news is incomplete. Flat (`newsOutput` `rows`): one `article` row per headline. Each headline has `id`, `title`, `publisher`, `link`, `publishedAt`, `contentType`, `summary`, `thumbnailUrl`, `relatedTickers`, `source` (`search`, `rss` or `search+rss`), `taggedWithTicker` (Yahoo tagged the article with your symbol) and `inTickerFeed` (it came in your symbol's own feed), newest first; flat rows also carry `allRoutesRead`. On the search route every field was filled for 921 of 921 US items except the thumbnail (790); feed items carry a `summary` and no publisher. `name` on news rows is filled when the quote was asked in the same run.

Example article row (platform run, NVDA, flat news):

```json
{
  "type": "article",
  "symbol": "NVDA",
  "name": null,
  "id": "0b7ec0e8-8667-3730-9383-852adf4ca9b9",
  "title": "CoreWeave (CRWV) Unveils Forge For AI Development",
  "publisher": "Simply Wall St.",
  "link": "https://finance.yahoo.com/technology/ai/articles/coreweave-crwv-unveils-forge-ai-020922457.html",
  "publishedAt": "2026-10-01T02:09:22.000Z",
  "contentType": "STORY",
  "summary": "CoreWeave (NasdaqGS:CRWV) unveiled Forge, a unified AI development environment, at its Fully Connected AI cloud conference. ...",
  "thumbnailUrl": "https://media.zenfs.com/en/simply_wall_st__316/44525c174d97ebe37fab75bc64158db1.jpg",
  "relatedTickers": ["CRWV", "NVDA"],
  "source": "search+rss",
  "taggedWithTicker": true,
  "inTickerFeed": true,
  "scrapedAt": "2026-10-01T04:46:37.904Z"
}
```

#### Options: `options` record per expiry

One record per expiry date, nearest first, with `expirationDate`, `underlyingPrice`, `underlyingPriceTime`, `callCount`, `putCount`, `strikeCount`, `expirationDates` (every expiry Yahoo lists), `hasMiniOptions`, and the lists `calls` and `puts`. Each contract keeps Yahoo's 15 fields: `contractSymbol`, `strike`, `currency`, `lastPrice`, `change`, `percentChange`, `volume`, `openInterest`, `bid`, `ask`, `contractSize`, `expiration`, `lastTradeDate`, `impliedVolatility`, `inTheMoney`. On 3,546 contracts every field was filled except `volume` (96.2%).

#### Screeners: `quote` rows

A screener row is a Quote row with three more fields: `screener` (the id), `screenerTitle` and `screenerRank` (1 is the top of the list). A symbol that already came back as a quote earlier in the same run is delivered again, free, with `repeatedInRun: true`, so every list is complete and no quote is charged twice.

#### Status rows (free)

Every ticker that did not get every data type it asked for gets at most ONE `type: "status"` row with `scope: "ticker"`, `status`, `symbol`, `position`, `message`, `blocks` (each missing data type and its outcome), `details` (Yahoo's reason per data type), `deliveredBlocks` (the data types that did come) and, for an unknown symbol, `suggestions` (up to 5 of Yahoo's own candidates: `symbol`, `name`, `exchange`, `quoteType`). An input value that cannot be used gets a row with `scope: "input"`, `status: "invalid"`, `field`, `value` and `message`; a screener that returned nothing gets a row with `scope: "screener"`. None of them is charged.

| `status` | What it means |
|---|---|
| `not_found` | Yahoo does not know the symbol: its quote endpoint left it out twice, or another endpoint answered "not found". The other data types are not asked. |
| `no_data` | Yahoo knows the symbol but has nothing of this kind: no statements for an index, fund, currency or crypto asset; no options for a fund; no profile for an index; no price for a delisted shell listing. |
| `blocked` | Yahoo could not be reached for this part after several attempts. Run it again. |
| `unsupported` | Yahoo does not serve the request as asked, for example an interval it answers at another granularity for that window. |
| `skipped` | Not processed: the run stopped first (your maximum charge per run, the run timeout, or an abort). |
| `failed` | An unexpected error; `details` says what. |
| `invalid` | An input value that cannot be used: not a ticker symbol, a date that is not a date, an intraday window outside Yahoo's limits (the history data type is then not run), or no tickers and no screener at all. |

Two real status rows from platform runs (shortened: `details` and `scrapedAt` left out, the second also cut to two data types):

```json
{"type": "status", "scope": "ticker", "status": "no_data", "symbol": "^GSPC", "position": 1, "message": "Yahoo Finance has no data of this kind for the symbol. Nothing was charged for the missing part.", "blocks": {"financials": "no_data", "profile": "no_data"}, "deliveredBlocks": ["quote", "history"]}
{"type": "status", "scope": "ticker", "status": "not_found", "symbol": "ZZZZNOTREAL1", "position": 0, "message": "Yahoo Finance does not know this symbol. Nothing was charged for it.", "blocks": {"quote": "not_found", "history": "not_found"}, "deliveredBlocks": []}
```

The last row of every run is a free `type: "summary"` row with `tickersGiven`, `tickers`, `duplicateTickersIgnored`, `inputProblems`, `rows` (counts per row type), `tickerOutcomes`, `stoppedBy`, `requests`, `suggestionLookups` and `billing` (events charged per event name). A run writes at most 1,000 status rows; any beyond that are counted in `statusRowsOmitted`.

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

You pay per data row delivered plus a small start fee per run. Status rows, repeated screener rows and the run summary are free.

| Event | FREE | BRONZE | SILVER | GOLD |
|---|---|---|---|---|
| Quote (one Quote row or one screener row) | $0.40 / 1,000 | $0.40 / 1,000 | $0.36 / 1,000 | $0.32 / 1,000 |
| Ticker record (one history, financials, profile, analyst or news record, or one option expiry) | $0.065 / 1,000 | $0.065 / 1,000 | $0.058 / 1,000 | $0.052 / 1,000 |
| Candle (one flat price history row) | $0.02 / 1,000 | $0.02 / 1,000 | $0.018 / 1,000 | $0.016 / 1,000 |
| News article (one flat headline row) | $0.02 / 1,000 | $0.02 / 1,000 | $0.018 / 1,000 | $0.016 / 1,000 |
| Actor start (once per run, per GB of memory) | $0.0004 | $0.0004 | $0.0004 | $0.0004 |

Platinum and Diamond plans pay the Gold price. The Actor start event is a flat fee with no tier discount, charged once per run whatever the run delivers; the default 256 MB run counts as one start event.

Worked examples (start fee included):

| Run | FREE and BRONZE | SILVER | GOLD |
|---|---|---|---|
| 1 ticker, quote only: $0.0004 + 1 x $0.0004 | $0.0008 | $0.00076 | $0.00072 |
| 3 tickers, quote only (the prefill): $0.0004 + 3 x $0.0004 | $0.0016 | $0.00148 | $0.00136 |
| 1 ticker, every data type, one option expiry: $0.0004 + 1 Quote + 6 Ticker records ($0.0004 + 6 x $0.000065 = $0.00079) | $0.00119 | $0.001108 | $0.001032 |
| 5 tickers, every data type, one option expiry each: $0.0004 + 5 x $0.00079 | $0.00435 | $0.00394 | $0.00356 |
| 100 tickers, quote only: $0.0004 + 100 x $0.0004 | $0.0404 | $0.0364 | $0.0324 |
| 1 ticker, one year of daily candles as flat rows (Yahoo returned 251): $0.0004 + 251 x $0.00002 | $0.00542 | $0.004918 | $0.004416 |
| The same year as one nested history record: $0.0004 + 1 x $0.000065 | $0.000465 | $0.000458 | $0.000452 |
| One screener, 25 rows: $0.0004 + 25 x $0.0004 | $0.0104 | $0.0094 | $0.0084 |

Without the start fee, a ticker with every data type and one option expiry costs $0.00079 at FREE and BRONZE, $0.000708 at SILVER and $0.000632 at GOLD; each extra option expiry adds one Ticker record.

The Store pricing card shows these same prices per 1,000 events: "$0.40 / 1,000" on the Quote row means one quote costs 0.04 cents.

What is free (no event other than the start fee): a ticker Yahoo does not know, a data type Yahoo has nothing for, a blocked request, an invalid input value, a symbol that already had its quote in the same run (from the ticker list or another screener), every status row and the run summary. Rows are charged only after they are in your dataset, and your maximum charge per run is respected: rows that do not fit are not delivered, and each ticker affected gets a free `skipped` status row. A platform restart never delivers or charges a row twice.

### Input

| Field | Default | What it does |
|---|---|---|
| `tickers` | (prefill: AAPL, MSFT, NVDA) | Yahoo Finance symbols, one per line. Lower case, a leading `$` and a `finance.yahoo.com/quote/...` link are accepted; one line may hold several symbols separated by commas. Duplicates are dropped. A value that is not a symbol becomes a free `invalid` row, and a symbol Yahoo does not know a free `not_found` row, each with Yahoo's own suggestions when it has some. |
| `dataTypes` | `["quote"]` | Any of `quote`, `history`, `financials`, `profile`, `analyst`, `news`, `options`. |
| `historyRange` | `1mo` | `1d`, `5d`, `1mo`, `3mo`, `6mo`, `1y`, `2y`, `5y`, `10y`, `ytd`, `max`. Ignored when a start date is set. `max` is everything Yahoo has. |
| `historyInterval` | `1d` | `1m`, `2m`, `5m`, `15m`, `30m`, `60m`, `90m`, `4h`, `1d`, `5d`, `1wk`, `1mo`, `3mo`. |
| `historyStart` | empty | First day, `YYYY-MM-DD` (UTC). Replaces the range. |
| `historyEnd` | empty | Last day, `YYYY-MM-DD` (UTC), inclusive. Needs a start date. Empty means up to now. |
| `historyOutput` | `nested` | `nested`: one Ticker record per ticker. `rows`: one Candle row per candle. |
| `includePrePost` | `false` | Intraday intervals only: add pre-market and after-hours candles. |
| `statements` | all three | `income`, `balance`, `cashflow`. |
| `statementPeriods` | `["annual", "quarterly"]` | `annual`, `quarterly`, `trailing` (trailing twelve months, income and cash flow only). |
| `maxNewsPerTicker` | 20 | Newest headlines per ticker, 1 to 50. |
| `newsOutput` | `nested` | `nested`: one Ticker record per ticker. `rows`: one News article row per headline. |
| `maxOptionExpirations` | 1 | Expiry dates per ticker, nearest first, 1 to 60. Each is one Ticker record. |
| `screeners` | none | Yahoo's predefined lists, run with or without tickers: `day_gainers`, `day_losers`, `most_actives`, `trending_us`, `most_watched_tickers`, `most_shorted_stocks`, `fifty_two_wk_gainers`, `fifty_two_wk_losers`, `undervalued_growth_stocks`, `undervalued_large_caps`, `strong_undervalued_stocks`, `growth_technology_stocks`, `aggressive_small_caps`, `small_cap_gainers`, `high_dividend_yield`, `morningstar_five_star_stocks`, `upside_breakout_stocks_daily`, `the_acquirers_multiple`, `day_gainers_dji`, `day_losers_dji`, `most_actives_dji`, `day_gainers_ndx`, `most_actives_gb`, `day_gainers_gb`, the eleven sectors `ms_basic_materials` to `ms_utilities`, `top_etfs_us`, `top_performing_etfs`, `most_actives_etfs`, `technology_etfs`, `bond_etfs`, `top_mutual_funds`, `portfolio_anchors`, `solid_large_growth_funds`, `solid_midcap_growth_funds`, `conservative_foreign_funds`, `high_yield_bond`, `all_cryptocurrencies_us`, `most_actives_options`, `top_options_open_interest`, `top_options_implied_volatality` (Yahoo's own spelling). 49 predefined screeners plus the US trending tickers list. |
| `maxScreenerRows` | 25 | Top rows per screener, 1 to 250 (the trending list has at most 50). |

There is no proxy setting, API key or login field. Requests go out directly from the run, and a retry goes through the Apify datacenter proxy, at no extra charge to you. Runs use 256 MB of memory and a 1 hour default timeout; a run that reaches its timeout writes its summary and keeps the rows and charges made so far.

### Limits Yahoo sets

- **Intraday candles:** `1m` needs a start within the last 30 days and at most 8 days per run; `2m`, `5m`, `15m`, `30m` and `90m` need a start within the last 60 days; `60m` and `4h` within the last 730 days. A window outside these rules is refused before anything is asked or charged, with the rule in a free `invalid` row.
- **Full daily history:** `historyRange` `max` is asked as an explicit window from 1900, so daily candles come back as far as Yahoo has them (AAPL 11,542 candles from 1980-12-12; KO 16,295 from 1962-01-02).
- **Statement depth:** US companies return 4 to 5 annual and 5 to 7 quarterly periods per statement; other markets 4 to 5 annual, and the quarterly cash flow was empty for 8 of 15 (half year reporters). Older statements are not served.
- **News:** the search route returns 45 to 50 items at most for a US ticker and none for the 20 non US tickers tested; the RSS feed carried headlines for 19 of those 20. A ticker gets `no_data` only when both routes answered empty.
- **Options:** US stocks listed 12 to 28 expiry dates (`^SPX` 53); a fund, a crypto asset, a currency and most non US stocks have none (free `no_data`).
- **Screeners:** up to 250 rows per screener; the trending list carries at most 50 symbols.
- **Unknown names:** up to 25 suggestion lookups per run; values beyond that still get their free row, without suggestions.

### What this Actor does NOT do

- No real time or licensed exchange feed: rows carry Yahoo's own delay per exchange in `exchangeDataDelayedBy`, and the data is not meant for trading decisions.
- No data for delisted tickers: Yahoo answers them as unknown or as a listing without a price, and they come back as free status rows.
- No option Greeks, option filters, unusual activity lists or one flat row per option contract: the chain of an expiry comes nested in one record with Yahoo's own fields.
- No AI summaries or explanations.
- Statement periods come nested in one record per ticker, not as one flat row per period.
- No standalone search output and no news by free text query: a name or a typo comes back as a free row with Yahoo's candidates (up to 25 lookups per run), and news is by ticker.
- No market summary or sector tables, and no language or region setting.
- At most 50 news items per ticker.
- No ESG scores: Yahoo's route returned none for 60 of 60 symbols tested.
- No statements older than Yahoo serves on this route: about 4 to 5 fiscal years and 5 to 7 quarters.
- Dividends and splits come as lists inside the history record, not as rows of their own.
- No custom screener queries: the predefined lists only.
- No memory between runs: a scheduled run delivers and charges its rows again, and there are no alerts and no change detection.
- No guessing of a ticker from a company name: every value is read as a symbol exactly as given.

### About the data

The data is Yahoo Finance's public data as Yahoo shows it, read from the same public JSON endpoints the Yahoo Finance website uses. Quotes are delayed per exchange as the `exchangeDataDelayedBy` field says. Respecting Yahoo's terms and the rights of the exchanges and data providers behind the data is your responsibility. Nothing here is investment advice.

### API examples

Every run is also a Yahoo Finance API call over the Apify API: send the input, read the rows.

curl (synchronous run, returns the rows):

```bash
curl -X POST "https://api.apify.com/v2/acts/automation_craft~yahoo-finance-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"tickers":["AAPL","MSFT","NVDA"],"dataTypes":["quote"]}'
```

Node.js with `apify-client`:

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation_craft/yahoo-finance-scraper').call({
    tickers: ['AAPL', 'MSFT', 'NVDA'],
    dataTypes: ['quote'],
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const row of items) if (row.type === 'quote') console.log(row.symbol, row.regularMarketPrice, row.currency, row.exchangeDataDelayedBy);
```

Python with `apify-client`:

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("automation_craft/yahoo-finance-scraper").call(
    run_input={"tickers": ["AAPL", "MSFT", "NVDA"], "dataTypes": ["quote"]}
)
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
    if row["type"] == "quote":
        print(row["symbol"], row.get("regularMarketPrice"), row.get("currency"), row.get("exchangeDataDelayedBy"))
```

### FAQ

#### Is there an official Yahoo Finance API?

This Actor is not an official Yahoo product. It reads the public JSON endpoints behind finance.yahoo.com with no login and no API key, and gives you the result as rows you can fetch through the Apify API, so you do not need a key of your own.

#### Is Yahoo Finance data real time or delayed?

It depends on the exchange, and every Quote row says it in `exchangeDataDelayedBy` (minutes) and `quoteSourceName`. In our sample US exchanges, currencies and crypto read 0 minutes, London, XETRA, Paris, Hong Kong and the Indian exchanges 15, Tokyo and ASX 20, and CME group futures 10.

#### Can I get quarterly financial statements from Yahoo Finance?

Yes. Pick the Financial statements data type and set `statementPeriods` to `quarterly` (alone or with `annual` and `trailing`); you get the income statement, balance sheet and cash flow under Yahoo's own line names. Yahoo serves about 5 to 7 quarters and 4 to 5 years; older periods are not available on this route.

#### Does it work for delisted stocks?

No. Yahoo answers a delisted symbol as unknown or as a listing without a price, and the Actor returns a free `not_found` or `no_data` status row for it instead of charging you.

#### How do I get Yahoo Finance data into Google Sheets?

Run the Actor with `historyOutput` or `newsOutput` set to `rows` for one row per candle or headline, then export the dataset as CSV or Excel, or connect the run to Google Sheets, n8n or Make through Apify's integrations with the same input JSON.

#### Why does this Actor run with limited permissions?

It runs with Apify's limited permissions, the least privilege level: it reads its input and writes only its own run's dataset, which it also reads back after a platform restart so no row is delivered or charged twice. It opens no named store and touches nothing else in your account.

### Changelog

See the Changelog tab of this Actor (CHANGELOG.md in the source).

### More data tools by Automation Craft

- [Google News Scraper: Search, Topics, Decoded URLs](https://apify.com/automation_craft/google-news-scraper)
- [Google Trends Scraper - Compare and Trending Now](https://apify.com/automation_craft/google-trends-scraper)
- [ESPN Scraper: Scores, Standings, Stats, Odds](https://apify.com/automation_craft/espn-sports-scraper)
- [Bulk WHOIS & RDAP Domain Lookup: DNS, SSL](https://apify.com/automation_craft/domain-whois-rdap-lookup)
- [US New Business Registrations Scraper - LLC Leads](https://apify.com/automation_craft/us-new-business-registrations-scraper)
- [Amazon Product Scraper - Search, Best Sellers](https://apify.com/automation_craft/amazon-data-scraper)
- [G2 Reviews Scraper: Ratings, Pros and Cons](https://apify.com/automation_craft/g2-reviews-scraper)

This Actor is an independent tool and is not affiliated with or endorsed by Yahoo. It reads only publicly available Yahoo Finance data.

# Changelog

This Actor's version history is a separate document: https://apify.com/automation_craft/yahoo-finance-scraper/changelog.md

# Actor input Schema

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

Yahoo Finance ticker symbols, exactly as Yahoo shows them: AAPL, BRK-B, ^GSPC (index), EURUSD=X (currency), BTC-USD (crypto), ES=F (future), 0700.HK or RELIANCE.NS (other exchanges). Lower case, a leading $ and a pasted finance.yahoo.com quote link are accepted. A symbol Yahoo does not know costs nothing and comes back as a free row with Yahoo's own suggestions.

## `dataTypes` (type: `array`):

What to return for every ticker. quote: price, change, volume, market cap, ranges, valuation ratios and the exchange delay (one Quote row). history: candles with dividends and splits. financials: income statement, balance sheet and cash flow lines, annual and quarterly. profile: company or fund profile, key statistics, holders, insider transactions, filings. analyst: recommendations, price targets, estimates, earnings history, rating changes. news: latest headlines. options: the option chain per expiry. Each type other than quote is one Ticker record per ticker (options: one per expiry).

## `historyRange` (type: `string`):

How far back the candles go. Ignored when a start date is set. Yahoo keeps 1 minute candles for 30 days (at most 8 days per run), 2 to 90 minute candles for 60 days and 1 hour and 4 hour candles for 730 days; a window outside those limits is refused before anything is charged.

## `historyInterval` (type: `string`):

Length of one candle. Daily (1d) is the default; 1wk and 1mo give weekly and monthly candles; the minute and hour intervals are intraday and Yahoo keeps them for a limited time (see History range).

## `historyStart` (type: `string`):

Optional. First day of the window as YYYY-MM-DD (UTC). When set, it replaces the range. Example: 2020-01-01.

## `historyEnd` (type: `string`):

Optional. Last day of the window as YYYY-MM-DD (UTC), inclusive. Needs a start date. Empty means up to now.

## `historyOutput` (type: `string`):

nested: one Ticker record per ticker with the candles, dividends and splits inside (cheapest, one event per ticker). rows: one Candle row per candle, ready for CSV and spreadsheets (one small event per candle; dividends and splits are in the nested record only).

## `includePrePost` (type: `boolean`):

Intraday intervals only: also return candles from the extended trading sessions.

## `statements` (type: `array`):

Which statements to include.

## `statementPeriods` (type: `array`):

annual: the fiscal years Yahoo publishes (usually 4). quarterly: the latest quarters (usually 5). trailing: trailing twelve months figures for the income and cash flow statements.

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

Newest headlines to return per ticker, from 1 to 50. Yahoo usually has 15 to 30 for a large United States company and fewer or none for small or foreign ones.

## `newsOutput` (type: `string`):

nested: one Ticker record per ticker with the headlines inside (one event per ticker). rows: one News article row per headline, ready for CSV (one small event per headline).

## `maxOptionExpirations` (type: `integer`):

How many expiry dates to return per ticker, nearest first, from 1 to 60. Each expiry is one Ticker record with every call and put of that date.

## `screeners` (type: `array`):

Predefined Yahoo Finance screeners and the trending tickers list, returned as Quote rows (same fields as a quote, plus the screener name and the rank). 50 lists: gainers, losers, most active, 52 week highs and lows, value and growth screens, the eleven sectors, ETFs, mutual funds, cryptocurrencies and option lists. A symbol that already came back as a quote in the same run is repeated for free.

## `maxScreenerRows` (type: `integer`):

Top rows to return per screener, from 1 to 250 (the trending list has at most 50).

## Actor input object example

```json
{
  "tickers": [
    "AAPL",
    "MSFT",
    "NVDA"
  ],
  "dataTypes": [
    "quote"
  ],
  "historyRange": "1mo",
  "historyInterval": "1d",
  "historyOutput": "nested",
  "includePrePost": false,
  "statements": [
    "income",
    "balance",
    "cashflow"
  ],
  "statementPeriods": [
    "annual",
    "quarterly"
  ],
  "maxNewsPerTicker": 20,
  "newsOutput": "nested",
  "maxOptionExpirations": 1,
  "maxScreenerRows": 25
}
```

# Actor output Schema

## `items` (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 = {
    "tickers": [
        "AAPL",
        "MSFT",
        "NVDA"
    ],
    "dataTypes": [
        "quote"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation_craft/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",
        "NVDA",
    ],
    "dataTypes": ["quote"],
}

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

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation_craft/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/2vPMwRib4dXvvEbPW/builds/5u8eVYYMpPRaivulc/openapi.json
