{
"$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"
}