๐ŸŽ‰ Premium Proxies ยท 24-Hour Free TrialClaim Now
Guides

How to Scrape CoinMarketCap Crypto Prices

Scrape CoinMarketCap crypto prices, market cap, and historical data using the official API, the hidden data-api endpoints, and the __NEXT_DATA__ payload.

S SparkProxy 0 17 min read
Share
How to Scrape CoinMarketCap Crypto Prices

You can scrape CoinMarketCap for coin metadata, live prices, market cap, and historical OHLCV, but the naive approach (point BeautifulSoup at the ranking table) returns an empty page. CoinMarketCap runs on Next.js and sits behind Cloudflare: the table hydrates in the browser and paginates through an internal JSON API, so the HTML you download rarely holds the numbers you came for. This guide walks the three real data paths in the order you should reach for them. First the official CoinMarketCap API as the compliant choice, then the site's own data-api endpoints for what the free tier leaves out, then the __NEXT_DATA__ payload embedded in every page. Working Python is included, along with the Cloudflare and rate-limit handling that keeps a collector alive.

What You Can Pull from CoinMarketCap

CoinMarketCap tracks four broad kinds of data, and each has a cleanest source. Picking the wrong source is why most scrapers break.

Data you wantCleanest sourceNeeds an API key?
Coin list ranked by market capOfficial `listings/latest` or internal `data-api` listingOfficial yes, internal no
Live price, market cap, 24h volumeOfficial `quotes/latest` or internal `data-api`Official yes, internal no
Historical OHLCV / price seriesOfficial `ohlcv/historical` (paid) or internal chart endpointDepends
Coin metadata (logo, links, supply)Official `info` or `__NEXT_DATA__` on the coin pageOfficial yes, page no

The rule of thumb: if the official API returns the field on your plan, use it. It is documented, versioned, and stays inside the terms. Drop to the internal endpoints only for the specific things the free plan gates off, and treat those as brittle. If your goal is broader than CoinMarketCap alone, the wider workflow across exchanges, on-chain explorers, and NFT feeds lives in proxies for crypto data.


Start With the Official API

Before you scrape anything, get a free key from the CoinMarketCap developer portal. The official API is the sanctioned path: stable JSON, clear docs, and no fight with Cloudflare. It follows the same official-API-first logic covered in how to scrape stock market data.

The base URL is https://pro-api.coinmarketcap.com and every call authenticates with the X-CMC_PRO_API_KEY header. A latest-quote lookup for Bitcoin and Ethereum is a few lines:

import requests

BASE = "https://pro-api.coinmarketcap.com"
headers = {"X-CMC_PRO_API_KEY": "YOUR_CMC_KEY", "Accept": "application/json"}

r = requests.get(
    f"{BASE}/v2/cryptocurrency/quotes/latest",
    headers=headers,
    params={"symbol": "BTC,ETH", "convert": "USD"},
)
btc = r.json()["data"]["BTC"][0]["quote"]["USD"]
print(btc["price"], btc["market_cap"], btc["percent_change_24h"])

For the ranked table (the front page of CoinMarketCap), call listings/latest and page through it with start and limit:

r = requests.get(
    f"{BASE}/v1/cryptocurrency/listings/latest",
    headers=headers,
    params={"start": "1", "limit": "100", "convert": "USD", "sort": "market_cap"},
)
for coin in r.json()["data"]:
    q = coin["quote"]["USD"]
    print(coin["cmc_rank"], coin["symbol"], q["price"], q["market_cap"])

One endpoint is worth learning early: /v1/cryptocurrency/map. It returns the CoinMarketCap numeric ID for every coin. That ID is your stable join key, because symbols collide (there are dozens of coins ticking "SOL" or "UNI" across forks and scams) and slugs occasionally change. Map once, cache it, and key everything on the ID.


Free trial

Scraping at scale? Skip the blocks.

Fast, unblockable datacentre proxies with unlimited bandwidth.

What the Free API Tier Leaves Out

The free Basic plan is generous for live data and stingy for history. Two limits catch people out.

It is credit-based, not request-based. The Basic plan ships on the order of 10,000 call credits a month with a per-minute cap. CoinMarketCap has revised these numbers over time, so confirm the current figure on the pricing page, but the model matters more than the exact count. Credits are not requests. CoinMarketCap bills roughly one credit per 200 data points returned, and each extra convert currency multiplies the cost. A single listings/latest call for 5,000 coins in three fiat currencies can burn dozens of credits, not one. Request only the coins and conversions you need.

Historical OHLCV is gated. The ohlcv/historical and historical-quote endpoints have traditionally been reserved for paid tiers. Call one on a free key and you get a clean rejection rather than data:

r = requests.get(
    f"{BASE}/v2/cryptocurrency/ohlcv/historical",
    headers=headers,
    params={"symbol": "BTC", "time_start": "2025-01-01",
            "time_end": "2025-02-01", "interval": "daily", "convert": "USD"},
)
status = r.json()["status"]
print(status["error_code"], status["error_message"])
# 1006  "Your API Key subscription plan doesn't support this endpoint."

Those error_code values are worth memorizing because they tell you exactly what went wrong: 1006 means your plan cannot touch that endpoint, 1008 is the per-minute rate limit, 1010 is your monthly credit budget spent, and 1011 is an IP-level limit. When you need historical series without paying, the internal chart endpoint below returns the same data the coin page draws.


The Internal data-api Endpoints

The CoinMarketCap website fetches its own data from https://api.coinmarketcap.com/data-api/. These endpoints power the live site, take no API key, and return clean JSON. They are also undocumented, unversioned in practice, and can be renamed or removed without notice. Use them for the fields the free key gates off, and pin your parsing to what you observe today. The general discovery method (open DevTools, watch the Network tab, filter to Fetch/XHR, and read the request the page fires) is covered in depth in how to scrape hidden JSON API endpoints.

The listing endpoint is the internal twin of listings/latest:

import requests

url = "https://api.coinmarketcap.com/data-api/v3/cryptocurrency/listing"
params = {"start": 1, "limit": 100, "sortBy": "market_cap",
          "sortType": "desc", "convert": "USD", "cryptoType": "all"}
r = requests.get(url, params=params,
                 headers={"User-Agent": "Mozilla/5.0", "Accept": "application/json"})
for c in r.json()["data"]["cryptoCurrencyList"]:
    quote = c["quotes"][0]
    print(c["cmcRank"], c["symbol"], quote["price"], quote["marketCap"])

For history, the coin detail page reads a chart endpoint. Pass the CoinMarketCap ID and a range such as 1D, 7D, 1M, 1Y, or ALL:

url = "https://api.coinmarketcap.com/data-api/v3/cryptocurrency/detail/chart"
r = requests.get(url, params={"id": 1, "range": "1Y"},   # id 1 = Bitcoin
                 headers={"User-Agent": "Mozilla/5.0"})
points = r.json()["data"]["points"]
# points maps a unix timestamp to a value array: [price, volume, marketCap, ...]
for ts, point in list(points.items())[:3]:
    print(ts, point["v"][0])

Note the camelCase keys (cmcRank, marketCap, volume24h) versus the official API's snake_case (cmc_rank, market_cap, volume_24h). They are the same numbers under different names, so normalize both into one internal schema if you mix sources. The response shapes above are accurate as of writing; verify them in DevTools before you rely on them, because these are the endpoints most likely to shift.


Reading the __NEXT_DATA__ Payload

CoinMarketCap is built on Next.js. Every server-rendered page ships a