Find Top Performing Stocks

Site yahoofinance.comTask find-top-performing-stocks-22erj0Version v1Updated Jul 13, 2026Category finance

Return the N highest-performing single stocks on Yahoo Finance (Top/Day Gainers) ranked by percent change, with price, change, percent change, volume, market cap, and exchange. Read-only. This skill was captured from a live agent session on yahoofinance.com and publishes here verbatim, exactly as an agent receives it.

NoteSelectors and URL schemes drift as sites change. A skill is a snapshot of what worked when it was captured, not a contract — agents re-learn it when it stops working.

Purpose

Return the N highest-performing individual stocks on Yahoo Finance — the "Top Gainers" list ranked by intraday percent change. For each stock it returns symbol, company name, last price, absolute change, percent change, volume, market cap, and exchange. Read-only; never trades, logs in, or mutates anything.

Assumption made (no human to clarify): "highest performing single stocks" is interpreted as Yahoo Finance's headline Day Gainers list — the equities with the largest positive percent change in the current/most-recent US session — which is exactly what the site surfaces at /markets/stocks/gainers/. This list applies Yahoo's built-in liquidity/size floors (see Gotchas), so it is the "top performers among real, tradeable large/mid-cap names," not the absolute highest-percent movers including micro-caps. If you want the unfiltered highest movers, see the alternate scrIds in Gotchas.

When to Use

  • "Give me the top 5 (or N) performing / gaining stocks today."
  • Daily market-open or market-close monitoring of the biggest movers.
  • Seeding a watchlist or downstream analysis with the day's leaders.
  • Any flow that would otherwise scrape the Yahoo Finance "Top Gainers" table — the JSON API is faster, cheaper, and structurally stable.

Workflow

Yahoo Finance's "Top Gainers" page is a thin client over a public predefined-screener JSON API that needs no crumb, no auth, no cookies, and no residential proxy. A plain GET returns ranked results. Lead with the API; the browser path is a ~100× more expensive fallback that returns the identical data.

GET https://query1.finance.yahoo.com/v1/finance/screener/predefined/saved
    ?scrIds=day_gainers
    &count=5
    &formatted=false
  • scrIds=day_gainers is the "Top Gainers" list (ranked by regularMarketChangePercent descending).
  • count=N caps how many rows you get back (use the N the user asked for).
  • formatted=false returns raw numeric values (32.7582). Omit it (or formatted=true) to get {raw, fmt} objects ({"raw":32.7582,"fmt":"+32.76%"}) if you want display strings.
  • query2.finance.yahoo.com is an interchangeable mirror.

A plain curl (or any HTTP client) works — no proxy needed. Under restricted egress, run it through browserless_function. That runs in a browser page context, so a bare fetch has no egress until the page is navigated on-origin: page.goto the API host first, then page.evaluate a same-origin fetch:

export default async function ({ page }) {
  await page.goto("https://query1.finance.yahoo.com/", {
    waitUntil: "domcontentloaded",
  });
  const data = await page.evaluate(async () => {
    const r = await fetch(
      "/v1/finance/screener/predefined/saved?scrIds=day_gainers&count=5&formatted=false",
    );
    return r.json();
  });
  // project inside the function — don't ship the raw payload back
  const d = data.finance.result[0];
  return {
    data: { title: d.title, total: d.total, quotes: d.quotes },
    type: "application/json",
  };
}

2. Parse the result

The payload is finance.result[0] with:

  • title"Day Gainers"
  • total → full count of matching stocks (e.g. 173); count → how many were returned
  • quotes[] → already sorted by regularMarketChangePercent descending

For each quotes[i] read:

  • symbol, shortName (fallback longName)
  • regularMarketPrice, regularMarketChange, regularMarketChangePercent
  • regularMarketVolume, marketCap, fullExchangeName
  • quoteType (will be "EQUITY" — predefined gainers are single stocks, not ETFs/funds), marketState
curl -s "https://query1.finance.yahoo.com/v1/finance/screener/predefined/saved?scrIds=day_gainers&count=5&formatted=false" > /tmp/g.json
node -e '
const fs=require("fs");
const d=JSON.parse(fs.readFileSync("/tmp/g.json","utf8")).finance.result[0];
console.log(d.title, "of", d.total);
d.quotes.slice(0,5).forEach((q,i)=>console.log(`${i+1}. ${q.symbol} ${q.shortName} ${q.regularMarketChangePercent.toFixed(2)}% @ ${q.regularMarketPrice}`));
'

(If you fetched via browserless_function, data.finance.result[0] is already the parsed object — drop the outer JSON.parse.)

3. Emit the ranked list

Take the first N quotes (already in descending-percent order) and shape them into the Expected Output below. Done — no pagination needed for a top-N request.

Browser fallback (only if the API is unreachable)

The API has no auth and no anti-bot, so the browser path should rarely be needed. If you must, one browserless_agent call (the session persists across calls, keyed by proxy/profile — nothing to release):

// browserless_agent commands (no proxy arg)
{ "method": "goto", "params": { "url": "https://finance.yahoo.com/markets/stocks/gainers/", "waitUntil": "load", "timeout": 45000 } },
{ "method": "waitForTimeout", "params": { "time": 3500 } },   // table hydrates after load
{ "method": "screenshot", "params": { "fullPage": false } }

The page renders the same "Top Stock Gainers Today" table (Symbol / Name / Price / Change / Change % / Volume). The bare yahoofinance.com domain 301-redirects to finance.yahoo.com. Prefer the screenshot (read with vision) or an evaluate that parses the table rows over a raw text/html grab — the page body is mostly Yahoo nav chrome and sometimes leads with an "Oops, something went wrong" fragment even when the table is present. Validated 2026-05-31: the rendered table (DELL 420.91 / +103.86 / +32.76% / 38.022M) matched the API row exactly.

Site-Specific Gotchas

  • day_gainers is filtered, not the raw top %. The predefined screener applies Yahoo's built-in floors (US region, minimum price, minimum intraday market cap, minimum volume). So the #1 row may be a large-cap up 30%, while a micro-cap up 85% won't appear. For broader/unfiltered movers use a different scrIds: small_cap_gainers (verified: surfaced REPL +85.68% vs. day_gainers' top of +32.76%), or build a custom screener (see crumb gotcha). Pick the list that matches the user's intent and state which list you used in your answer.
  • Predefined screener (/v1/finance/screener/predefined/saved) needs NO crumb. A plain GET returns 200 (verified with and without a residential proxy). It sets A1/A3 cookies in the response but does not require any on the request.
  • Custom screeners DO need a crumb + cookie. The unfiltered query endpoint POST /v1/finance/screener?crumb=... requires first fetching a session cookie from any Yahoo page, then GET /v1/test/getcrumb with that cookie. Only go down this path if a predefined scrIds doesn't fit; for "top N gainers" the predefined list is sufficient and crumb-free.
  • formatted=false vs default. Default responses wrap every numeric in {raw, fmt}. Pass formatted=false for plain numbers, which is simpler to parse.
  • count caps the rows; total is the full match count. count=5 returns 5 quotes but total may read 173 — don't mistake total for "stocks up today."
  • Results are pre-sorted descending by percent change. No client-side sort needed; quotes[0] is the top performer.
  • Market-closed = static, last-session values. On weekends/holidays marketState is CLOSED and the percentages reflect the last trading session's close (the list is stable, not live). Re-fetching returns identical numbers until the next session.
  • All rows are quoteType: "EQUITY" — the predefined gainers list is single stocks only, so it already satisfies "single stocks" (no ETFs/funds to filter out).
  • API host ≠ web host. The data lives on query1/query2.finance.yahoo.com; the human page is finance.yahoo.com. The bare yahoofinance.com 301-redirects to finance.yahoo.com.
  • No anti-bot wall observed. Pre-run probe reported no antibots; API fetched 200 both with and without a proxy; the gainers page loaded directly with no consent/captcha interstitial. No stealth or residential proxy arg was required for any successful step.

Expected Output

{
  "source": "yahoo_finance",
  "list": "day_gainers",
  "list_title": "Day Gainers",
  "ranked_by": "regularMarketChangePercent_desc",
  "market_state": "CLOSED",
  "total_matching": 173,
  "as_of": "2026-05-31",
  "stocks": [
    {
      "rank": 1,
      "symbol": "DELL",
      "name": "Dell Technologies Inc.",
      "price": 420.91,
      "change": 103.86,
      "change_percent": 32.76,
      "volume": 38175314,
      "market_cap": 273409769472,
      "exchange": "NYSE",
      "quote_type": "EQUITY"
    },
    {
      "rank": 2,
      "symbol": "OKTA",
      "name": "Okta, Inc.",
      "price": 123.27,
      "change": 28.55,
      "change_percent": 30.14,
      "volume": 17181770,
      "market_cap": 21614956544,
      "exchange": "NasdaqGS",
      "quote_type": "EQUITY"
    },
    {
      "rank": 3,
      "symbol": "NTAP",
      "name": "NetApp, Inc.",
      "price": 174.29,
      "change": 31.89,
      "change_percent": 22.39,
      "volume": 15902415,
      "market_cap": 34519937024,
      "exchange": "NasdaqGS",
      "quote_type": "EQUITY"
    },
    {
      "rank": 4,
      "symbol": "TBBB",
      "name": "BBB Foods Inc.",
      "price": 37.82,
      "change": 5.09,
      "change_percent": 15.55,
      "volume": 6205247,
      "market_cap": 4457357312,
      "exchange": "NYSE",
      "quote_type": "EQUITY"
    },
    {
      "rank": 5,
      "symbol": "TEAM",
      "name": "Atlassian Corporation",
      "price": 107.61,
      "change": 14.32,
      "change_percent": 15.35,
      "volume": 13829691,
      "market_cap": 27307958272,
      "exchange": "NasdaqGS",
      "quote_type": "EQUITY"
    }
  ]
}

Note: the example values are a captured snapshot (US market CLOSED, 2026-05-31). Live values change each session, but the shape and the descending-percent ordering are stable.

Call it

GET https://production-sfo.browserless.io/skills?token=TOKEN-HERE&domain=yahoofinance.com&task=find-top-performing-stocks-22erj0