Yahoo Options Scraper [💰$1.2/1K] | Greeks | IV | Live Chains avatar

Yahoo Options Scraper [💰$1.2/1K] | Greeks | IV | Live Chains

Pricing

from $1.17 / 1,000 results

Go to Apify Store
Yahoo Options Scraper [💰$1.2/1K] | Greeks | IV | Live Chains

Yahoo Options Scraper [💰$1.2/1K] | Greeks | IV | Live Chains

Extract Yahoo Finance options chains with full Greeks, volume and implied volatility data for any ticker. Build options screeners, volatility research and pricing models.

Pricing

from $1.17 / 1,000 results

Rating

5.0

(1)

Developer

Ahmed Jasarevic

Ahmed Jasarevic

Maintained by Community

Actor stats

2

Bookmarked

198

Total users

30

Monthly active users

9 days ago

Last modified

Share

Yahoo Finance Options Scraper

Scrapes Yahoo Finance option chains over plain HTTP — no API key, no browser, no headless Chrome.

It returns both calls and puts across multiple expirations, in three output modes, and computes Greeks locally with Black-Scholes-Merton because Yahoo does not provide them.


What it does

Transportgot-scraping over HTTP, sticky Apify proxy session, cookie + crumb handshake
Data sourceYahoo's public /v7/finance/options/{ticker} endpoint, plus /v8/finance/chart/^IRX for the risk-free rate
Modeschain (one row per contract), summary (one row per ticker), unusual (unusual-activity scanner)
ExpirationsUp to 12 per ticker in a single run, not just the nearest one
GreeksComputed locally: delta, gamma, theta, vega, rho, theoretical price
Risk-free rateFetched from ^IRX automatically; falls back to 4.5%, or set your own via riskFreeRate
Free tierCapped at 50 output rows. Every row is billed identically

Runs that fail produce a non-zero exit and a clear error. It never reports success on empty or partial results.


Quick start

{
"tickers": ["AAPL", "SPY", "NVDA"],
"optionsExpirations": 4,
"maxItems": 2000
}

From the CLI:

$apify run -i '{"tickers":["AAPL","SPY"],"mode":"summary"}'

Input

Unknown fields are rejected with an error, not silently ignored. A misspelled key is the fastest way to quietly get wrong data back, so the run fails instead and lists the valid fields.

Tickers

tickers accepts an array or a string. Strings may be comma- or space-separated. Symbols are uppercased and de-duplicated. Supports stocks, ETFs, indices (^GSPC), futures (ES=F), crypto pairs (BTC-USD) and FX pairs (EURUSD=X). Dash style is converted to Yahoo's dot style, so BRK-B becomes BRK-B on the wire.

  • Default: ["AAPL"]
  • Max: 50 per run

What to scrape

FieldDefaultNotes
modechainchain, summary or unusual
contractTypes["calls","puts"]calls, puts, or both. both / all also accepted
optionsExpirations1How many nearest expirations to fetch (max 12)
expirationDates—Exact YYYY-MM-DD dates. Takes priority over the range inputs
expirationFrom / expirationTo—Inclusive date range
includeGreekstrueComputes Greeks locally
riskFreeRateautoDecimal, e.g. 0.043. Overrides the ^IRX fetch

expirationDates wins over expirationFrom/expirationTo when both are set.

The default of optionsExpirations: 1 fetches the nearest expiry, which is often 0–2 days out. Greeks on a contract with almost no time left are close to meaningless. If you want usable Greeks or a 30-day IV term structure, raise this — "optionsExpirations": 12 reaches roughly one month out. The nearest expiry costs no extra request; each additional one is one more HTTP call.

Filtering

FieldNotes
moneynessall, inTheMoney, outOfTheMoney, atTheMoney
minStrike / maxStrikeAbsolute strike bounds
strikeWindowPercentKeep strikes within N% of spot
minVolume, minOpenInterestLiquidity floors
minImpliedVolatility, maxImpliedVolatilityDecimal, e.g. 0.3 for 30%
minDaysToExpiration, maxDaysToExpirationDTE window
atmEpsilonPercentHow close to spot counts as ATM. Default 1.5

atTheMoney is resolved against atmEpsilonPercent, not a fixed price distance. A tolerance smaller than the ticker's strike spacing matches nothing, so the minimum accepted value is 0.1.

Output shape

FieldDefaultNotes
maxItems1000Caps rows across the whole run, not per ticker. Max 25000
sortByyahooOrderSee below
concurrency4Tickers fetched in parallel over one sticky session (max 8)
maxRetries3Retries per request before the run fails (max 5)
requestDelayMs0Delay between requests
proxyConfiguration—Passed through to Apify proxy settings

sortBy accepts yahooOrder, strikeAsc, strikeDesc, volumeDesc, openInterestDesc, impliedVolatilityDesc, impliedVolatilityAsc, premiumDesc, lastTradeNewest, nearestStrike, moneynessAsc.

With several tickers and a maxItems cap, rows are allocated round-robin across tickers so no single ticker eats the whole budget. Note that unusual mode ranks by score within each ticker, then interleaves.

Unusual mode thresholds

FieldDefault
unusualVolumeOiRatio5 — flag when volume is at least 5x open interest
unusualPremiumUsd50000 — flag when estimated traded premium reaches this

Contracts with no open interest yet qualify on volume alone, since a fresh position has no OI to compare against.


Modes

chain

One row per contract. Both calls and puts, across every selected expiration. This is the default.

summary

One row per ticker with aggregated metrics: total and per-side volume, open interest, put/call ratios for both, average IV per side, the 30-day ATM IV block, net premium flow, premium traded, the most active contract, the max pain strike, and a sentiment label.

maxPainStrike is the strike at which the total payout to option holders is lowest, so the price tends to settle there. It is weighted by open interest, falls back to volume when a chain carries no open interest at all, and is null when neither exists. maxPainWeighting tells you which of the two was used.

Max pain is calculated from the full unfiltered chain for the nearest expiration — not from the rows you filtered. A minVolume or strike-window filter would otherwise leave too few contracts and produce a mathematically valid but meaningless number. The nearest expiration is reported in maxPainExpiration.

sentiment is a three-signal vote, not a single ratio:

  • net premium flow (call premium minus put premium)
  • put/call volume ratio — above 1.2 is bearish, below 0.8 is bullish
  • put/call open interest ratio — same thresholds

Majority wins, a tie is mixed, and no usable data is neutral. Premium flow on its own is a weak signal, so it needs confirmation from at least one of the other two.

unusual

Contracts that pass both unusual thresholds, ranked by unusualScore and then by traded premium. The score is 0.4 × log(volume/OI ratio) + 0.6 × log(premium), both on log scales. A linear scale saturates here — real premiums run from $100k to $10M, so a linear score collapses to two distinct values and cannot rank anything.


Output

rowType is contract or summary and tells you which shape you have. Fields that do not apply to a given row are null, never zero or an empty string.

Numeric fields are real numbers. impliedVolatility is a decimal fraction (0.32 = 32%), not the string "32.00". Prices, strikes, Greeks and volumes are all numbers, so spreadsheet tools and JSON consumers do not have to parse text.

Contract rows

  • Identity: contractSymbol, type, strike, expiration, expirationTimestamp, daysToExpiration
  • Quote: lastPrice, bid, ask, mid, spread, spreadPercent, change, percentChange, lastTradeDate
  • Volatility and Greeks: impliedVolatility, delta, gamma, theta, vega, rho, theoreticalPrice
  • Activity: volume, openInterest, volumeOpenInterestRatio, premiumTradedUsd
  • Moneyness: inTheMoney, moneyness (ITM/OTM/ATM), moneynessPercent
  • Underlying: underlyingPrice, underlyingChange, marketCap, trailingPE, forwardPE, fiftyTwoWeekLow, fiftyTwoWeekHigh, earningsDate, dividendYield

Conventions

  • theta is per calendar day.
  • vega is per one volatility point (a move of 0.01 in decimal IV).
  • rho is per one percentage point of interest rate.
  • premiumTradedUsd is lastPrice × volume × 100, using the standard US equity contract multiplier. It is an estimate built off the last trade price, so a contract with a stale print can look far more active than it is. volumeOpenInterestRatio is usually the more honest activity signal.
  • moneyness is a computed label, not a copy of Yahoo's flag. inTheMoney follows Yahoo's own field.

null means Yahoo had no data

This is important. null is not zero and not "the contract has no value":

  • bid and ask are 0 when Yahoo has no two-sided quote, which is common outside regular trading hours. When there is no quote at all, mid and spread are null rather than 0, because a spread of zero is a real claim about a market and this is not one.
  • impliedVolatility and all Greeks are null when Yahoo has no usable IV.
  • volumeOpenInterestRatio is null when a contract has no open interest yet.

Data quality, measured

This section is the part most option scrapers get wrong, so here are the actual observed numbers.

Yahoo quantizes implied volatility and clamps it at 50%

Sampling 2000 contracts across AAPL, SPY, NVDA, TSLA, AMD and KO:

PercentileIV
p10.39%
p103.13%
p5025.00%
p7550.00%
p9050.00%
p9950.00%

The values land on a quantized ladder — steps of roughly 0.001, frequently exact powers of two times 0.0078 — and 25% of all contracts came back at exactly the same value, 0.500005, which is the 50% ceiling rather than a real quote. Treat high IV readings from this source as suspiciously capped.

A large share of contracts have no IV at all

Only 1055 of 2000 contracts in that sample carried an IV above the 1% floor. Availability depends on the ticker, the strike and the session; deep out-of-the-money and near-expiry contracts are the worst affected.

IVs below 1% are treated as missing. Yahoo sends 0.00001 as a "no IV here" sentinel, and the low end of the ladder carries values like 0.0005 and 0.0039 that are artifacts rather than real volatilities. The floor is what keeps those from producing confident-looking Greeks with a delta of exactly 0 or 1.

Outside trading hours, the smile degenerates

With the market closed, the 30-day AAPL chain returned this IV ladder:

StrikeCall IVPut IV
3250.000010.0313
3300.000010.0156
3350.000010.0078
3400.00390.00001
3450.01560.00001
3500.03130.00001

Monotonic in strike, on the same power-of-two ladder, with essentially no volatility at the money. A real smile is U-shaped with a minimum at the money. This is not a smile. If you need reliable IVs, run during US regular market hours and check marketState on the underlying.

Greeks inherit all of the above

The Black-Scholes implementation is standard and unit-tested against known values, but it can only be as good as the IV it is handed. Greeks are null whenever the IV is missing or below the floor. Greeks on a 0-DTE contract are also near-meaningless by construction, since there is no time value left to differentiate.

The 30-day block is reported honestly or not at all

iv30d, ivSkew30d, atmCallIV30d, atmPutIV30d and expiration30d are only populated when an expiration genuinely close to 30 days out was fetched — within ±10 days — and Yahoo returned a usable ATM IV for it. Otherwise they are null. An earlier version reported whatever expiration happened to be nearest to 30 days, so a run covering only 0–7 DTE would label 7-day values as iv30d. It also reports the actual DTE in daysToExpiration30d so you can verify what you are looking at.

atmStrike is the strike nearest spot, not simply the lowest strike inside the ATM band.

Premium traded can be overstated

premiumTradedUsd multiplies today's volume by the last trade price. For a contract that has not traded recently, that price is stale and the figure inflates accordingly.


Known limitations

  • No historical option data. Current chains only.
  • IV is Yahoo's, quantized and capped at 50%. See above.
  • Greeks are model output, not exchange data. They are computed from Yahoo's IV, and are only as accurate as that IV.
  • No intraday or real-time option quotes. Bid and ask are whatever Yahoo last published.
  • Contract multiplier is assumed to be 100. Correct for US equity options, wrong for adjusted contracts, indexes and some adjusted symbols. premiumTradedUsd inherits this assumption.
  • DTE comes from Yahoo's own expiration list.
  • Not a full trading backtest. Sentiment and unusual scores are descriptive aggregates over one snapshot, not signals with demonstrated predictive value.

Charges and pricing

Billing is the Apify default: every dataset row is a chargeable result. The Actor uses the synthetic apify-default-dataset-item event, which Apify charges automatically for each item written to the run's default dataset. No extra charging code is needed and none is used.

This is also the simplest pricing you can have: one event, one price, and the user sees exactly what they pay for. Custom per-mode events (contract, summary, unusual) are deliberately not charged separately. To charge them, each would have to be registered as a paid event in the Apify Console, and because the rows also land in the default dataset, users would be billed twice unless apify-default-dataset-item were removed. More events also make costs harder for users to predict.

Free-tier users are capped at 50 rows and are billed the same per-row rate; they simply cannot request more. RUN_SUMMARY goes to the key-value store via setValue, which is not a dataset row and is not charged.


Development

npm install
npm test # 111 unit tests, no network required
npm start # local run; reads storage/key_value_stores/default/INPUT.json

To emulate a paying user locally:

$APIFY_USER_IS_PAYING=1 npm start

The unit tests cover Greeks against known Black-Scholes values, input validation, expiration selection, the round-robin allocator, every filter and sort, the unusual-activity gate and score, IV sentinel handling, 30-day honesty, the sentiment vote, unknown-field rejection, and the ATM tolerance default.

FilePurpose
main.jsOrchestration, mode dispatch, row pushing, run summary
src/yahoo.jsSticky proxy session, cookie/crumb handshake, retries, session refresh
src/rows.jsRow building, filters, sorting, summaries, unusual scoring
src/greeks.jsBlack-Scholes-Merton
src/input.jsValidation, normalization, unknown-field rejection
src/constants.jsDefaults, limits, tuning constants
src/util.jsNumeric and date helpers, concurrency

License

ISC