CoinGecko API: JavaScript and Python with Rate Limit Handling
Languages: JavaScript, Python · Estimated time: ~8 minutes · CoinGecko live status ↗
The CoinGecko Demo plan gives you 10–30 calls/minute with no key. Here's how to fetch prices, batch multiple coins in one call, and handle 429 rate limit errors gracefully.
CoinGecko's Demo plan requires no API key and covers 10,000+ coins. The main constraint is rate limiting: roughly 10–30 calls per minute. Exceed it and you get HTTP 429. This tutorial shows you how to stay under the limit and recover gracefully when you don't.
Live status at /coingecko — we monitor it hourly.
Fetching a Single Coin Price
The `/simple/price` endpoint is the most efficient for price lookups:
# Single coin, multiple currencies
curl "https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd,eur,gbp"
# Response:
# { "bitcoin": { "usd": 63450.12, "eur": 58920.44, "gbp": 50130.88 } } JavaScript: Batch Price Fetch with Rate Limit Handling
Batch your queries. The `ids` parameter accepts comma-separated CoinGecko IDs — one call for 50 coins is far better than 50 calls.
const COINGECKO_BASE = "https://api.coingecko.com/api/v3";
async function fetchPrices(coinIds, vsCurrencies = ["usd"]) {
const url = new URL(`${COINGECKO_BASE}/simple/price`);
url.searchParams.set("ids", coinIds.join(","));
url.searchParams.set("vs_currencies", vsCurrencies.join(","));
let retries = 0;
while (retries < 3) {
const res = await fetch(url);
if (res.status === 429) {
// Rate limited — wait and retry
const retryAfter = parseInt(res.headers.get("Retry-After") ?? "60");
console.warn(`Rate limited. Waiting ${retryAfter}s...`);
await new Promise(r => setTimeout(r, retryAfter * 1000));
retries++;
continue;
}
if (!res.ok) throw new Error(`CoinGecko error: ${res.status}`);
return await res.json();
}
throw new Error("Max retries exceeded");
}
// Usage: batch up to 50 coins in one call
const prices = await fetchPrices(
["bitcoin", "ethereum", "solana", "cardano"],
["usd", "eur"]
);
// { bitcoin: { usd: 63450, eur: 58920 }, ethereum: { ... }, ... } Python: Prices with Automatic Retry
import requests
import time
COINGECKO_BASE = "https://api.coingecko.com/api/v3"
def fetch_prices(coin_ids: list[str], vs_currencies: list[str] = ["usd"]) -> dict:
"""
Fetch prices for multiple coins. Handles 429 rate limit with retry.
"""
url = f"{COINGECKO_BASE}/simple/price"
params = {
"ids": ",".join(coin_ids),
"vs_currencies": ",".join(vs_currencies)
}
for attempt in range(3):
resp = requests.get(url, params=params, timeout=10)
if resp.status_code == 429:
retry_after = int(resp.headers.get("Retry-After", 60))
print(f"Rate limited, waiting {retry_after}s (attempt {attempt+1}/3)...")
time.sleep(retry_after)
continue
resp.raise_for_status()
return resp.json()
raise RuntimeError("CoinGecko rate limit exceeded after retries")
# Example: top 5 coins in USD and EUR
coins = ["bitcoin", "ethereum", "solana", "cardano", "polkadot"]
prices = fetch_prices(coins, ["usd", "eur"])
for coin, data in prices.items():
usd = data['usd']
eur = data['eur']
print(f"{coin}: USD {usd} / EUR {eur}") Looking Up a Coin's ID
CoinGecko uses its own ID system ('bitcoin', not 'BTC'). Use the `/coins/list` endpoint to find the right ID:
# Get full list of coin IDs (large response, cache this locally)
curl "https://api.coingecko.com/api/v3/coins/list" | grep -i '"solana"'
# Output: {"id":"solana","symbol":"sol","name":"Solana"} Rate Limit Tips
- Use a 60-second polling interval as your baseline. CoinGecko prices update every ~45 seconds anyway.
- Cache responses client-side. If multiple users request the same prices, serve from cache rather than calling the API per user.
- Batch multiple coins in a single /simple/price call. 50 coins = 1 call, not 50.
- The Demo plan's rate limit is soft — short spikes above 30 calls/min are often tolerated. Sustained over-limit usage gets blocked.
- If you need guaranteed higher limits, the free Demo API key (sign up at coingecko.com/en/api/pricing) is listed as 'Demo' and is also free — it just provides more predictable limits.