FreeAPI.watch

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.

Frequently Asked Questions

Do I need a CoinGecko API key?

No. The Demo plan (no key required) gives you access to most endpoints. You can optionally add a Demo API key in the x-cg-demo-api-key header to get higher rate limits, but it's not required to start.

What's the difference between CoinGecko and CoinPaprika?

CoinGecko covers 10,000+ coins and 800+ exchanges — broader coverage but rate-limited (10–30 calls/min). CoinPaprika covers 2,000+ coins, requires no key, and gives 25,000 calls/month with no per-minute rate limit. For breadth, use CoinGecko. For a cleaner free tier with predictable monthly budget, use CoinPaprika. See /coinpaprika for live status.

Why do I get different prices from different exchanges?

CoinGecko returns a volume-weighted average price across all tracked exchanges. Exchange-specific prices differ due to liquidity, regional premiums, and timing. If you need a specific exchange's price, use that exchange's public API (Binance, Kraken, Coinbase all offer free public price endpoints).

← All tutorials  ·  Check CoinGecko live status →