{
  "$type": "site.standard.document",
  "bskyPostRef": {
    "cid": "bafyreibtl2xxl4piodbjn7snk7m7nvevqwutkfory2sdsr6dpxpzfbbsdi",
    "uri": "at://did:plc:25rdn5elo5izoxrmtis34zuk/app.bsky.feed.post/3mpk7gcj3vpe2"
  },
  "coverImage": {
    "$type": "blob",
    "ref": {
      "$link": "bafkreiewpp7fz7phajkm3wkwwyrpm3gmweygoihfkdfkmlouxdpb4qn4v4"
    },
    "mimeType": "image/webp",
    "size": 60810
  },
  "path": "/scrapemint/pull-live-crypto-market-data-without-a-rate-limited-key-n06",
  "publishedAt": "2026-06-30T23:22:52.000Z",
  "site": "https://dev.to",
  "tags": [
    "webdev",
    "api",
    "javascript",
    "showdev"
  ],
  "textContent": "Crypto dashboards, alerts and portfolio trackers all need the same boring thing first: a clean list of coins with price, market cap, volume and recent change. The usual path is signing up for a data plan and babysitting an API key. You often do not need to.\n\n##  The keyless endpoint\n\nCoinGecko serves a public market endpoint that returns a tidy array of coins:\n\n\n\n    GET https://api.coingecko.com/api/v3/coins/markets\n        ?vs_currency=usd&order=market_cap_desc&per_page=250&page=1\n        &price_change_percentage=1h,24h,7d,30d\n\n\nNo key, no header, no login. Each coin comes back with the fields you actually want:\n\n  * `current_price`, `market_cap`, `market_cap_rank`\n  * `total_volume`, `fully_diluted_valuation`\n  * `circulating_supply`, `total_supply`, `max_supply`\n  * `ath`, `ath_change_percentage`, `atl`\n  * `price_change_percentage_24h_in_currency`, `_7d_`, `_30d_` and more\n\n\n\n##  Page in big chunks\n\nThe mistake that gets people rate limited is hammering the endpoint one coin at a time. Do the opposite. `per_page` goes up to 250, so a thousand coins is four requests, not a thousand. Walk the pages until you hit your cap or an empty page:\n\n\n\n    let page = 1, out = [];\n    while (out.length < cap) {\n      const res = await fetch(`${base}/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=250&page=${page}&price_change_percentage=1h,24h,7d,30d`);\n      if (res.status === 429) { await sleep(15000); continue; }\n      const data = await res.json();\n      if (!data.length) break;\n      out.push(...data);\n      if (data.length < 250) break;\n      page += 1;\n    }\n\n\nThe only thing to handle is the occasional `429`. A short backoff and retry is enough, because with `per_page=250` you make so few calls that you rarely hit it.\n\n##  Watchlist mode\n\nIf you only care about a few coins, pass `ids=bitcoin,ethereum,solana` and you get just those in a single call. Same shape, no filtering in your own code.\n\n##  I packaged it\n\nI turned this into a small Actor on Apify so it is callable from code without writing the paging by hand. You set a quote currency, a sort and a cap, or a list of coin ids for a watchlist, and it returns one row per coin with price, market cap and rank, volume, supply, all time high and low, and 1h to 30d change. It joins a growing set of keyless finance and market scrapers I have been shipping. The first rows of every run are free so you can check the output first.\n\nThe pattern generalizes: before you reach for a paid data plan, check whether the site you already trust serves the same numbers over a public endpoint. For crypto, it does.",
  "title": "Pull Live Crypto Market Data Without a Rate Limited Key"
}