Skip to main content
⚠️ Crypto markets are highly volatile and operate 24/7. This page is for educational and automation purposes only — not financial advice.
Crypto & DeFi · Part 1 of 5

Price & Market Data

Fetch live prices, OHLCV history, and market cap rankings with CoinGecko's free API — no key required for basic endpoints.

CoinGecko Free API No Key Required 30 req/min

CoinGecko Setup

The CoinGecko free API requires no API key for basic endpoints. You only need Python's built-in requests library to fetch live cryptocurrency data. Unlike other APIs, there's zero registration overhead — just start making calls.

Installation & First Call

Most Python installations include requests by default. If not, install it with pip install requests. Here's a simple function to fetch data from CoinGecko:

python
# No pip install needed — just requests (standard)
import requests
import json
from datetime import datetime

BASE = "https://api.coingecko.com/api/v3"

def cg_get(endpoint, params=None):
    """Rate-limited CoinGecko fetch."""
    import time
    resp = requests.get(f"{BASE}{endpoint}", params=params, timeout=10)
    resp.raise_for_status()
    return resp.json()

# Quick test — get BTC price
data = cg_get("/simple/price", {"ids": "bitcoin", "vs_currencies": "usd"})
print(f"BTC: ${data['bitcoin']['usd']:,.2f}")

This simple wrapper handles error checking and will be the foundation for all our examples. The timeout=10 parameter prevents hanging on slow network connections.

Top Coins by Market Cap

The /coins/markets endpoint returns detailed market data for the top cryptocurrencies by market capitalization. This is perfect for building a watchlist or dashboard of the largest crypto assets.

Fetching Top 20 Coins

Request the top 20 coins with 24h and 7d price changes in a single call:

python
def get_top_coins(limit=20):
    """Fetch top N coins by market cap."""
    coins = cg_get("/coins/markets", {
        "vs_currency": "usd",
        "order": "market_cap_desc",
        "per_page": limit,
        "page": 1,
        "sparkline": False,
        "price_change_percentage": "24h,7d"
    })
    return coins

coins = get_top_coins(20)
print(f"{'Rank':<5} {'Coin':<15} {'Price':>12} {'24h%':>8} {'7d%':>8} {'Mkt Cap':>15}")
print("-" * 65)
for c in coins:
    rank = c['market_cap_rank']
    name = c['symbol'].upper()
    price = c['current_price']
    d24 = c.get('price_change_percentage_24h') or 0
    d7 = c.get('price_change_percentage_7d_in_currency') or 0
    mcap = c['market_cap']
    arrow24 = "▲" if d24 > 0 else "▼"
    print(f"{rank:<5} {name:<15} ${price:>11,.4f} {arrow24}{abs(d24):>6.2f}% {'':>8} ${mcap:>13,.0f}")

Key parameters:

OHLCV Historical Data

OHLCV stands for Open, High, Low, Close, Volume. CoinGecko provides daily candle data via the /coins/{id}/ohlc endpoint, perfect for technical analysis and volatility studies.

Fetching Daily Candles

Retrieve 30 days of OHLCV data and calculate volatility metrics:

python
def get_ohlcv(coin_id: str, days: int = 30):
    """
    Fetch OHLCV data via CoinGecko market_chart.
    Returns DataFrame with [date, open, high, low, close].
    """
    data = cg_get(f"/coins/{coin_id}/ohlc", {
        "vs_currency": "usd",
        "days": days
    })
    # Each row: [timestamp_ms, open, high, low, close]
    import pandas as pd
    df = pd.DataFrame(data, columns=["timestamp_ms","open","high","low","close"])
    df["date"] = pd.to_datetime(df["timestamp_ms"], unit="ms")
    df = df[["date","open","high","low","close"]]
    return df

df = get_ohlcv("bitcoin", 30)
print(df.tail(5).to_string(index=False))

# Simple volatility check
df["daily_range_pct"] = (df["high"] - df["low"]) / df["open"] * 100
print(f"\nAvg daily range (30d): {df['daily_range_pct'].mean():.2f}%")
print(f"Max daily range (30d): {df['daily_range_pct'].max():.2f}%")

Valid day parameters: 1, 7, 14, 30, 90, 180, 365, max (all-time)

The daily range percentage helps identify volatile periods — useful for setting stop-losses or alert thresholds.

Price Alert System

Build a simple polling-based price alert system that respects CoinGecko's rate limits (30 req/min on free tier). We use a cooldown mechanism to prevent alert spam:

python
import time
import smtplib
from email.mime.text import MIMEText

WATCHLIST = {
    "bitcoin":  {"above": 75000, "below": 55000},
    "ethereum": {"above": 4500,  "below": 2800},
    "solana":   {"above": 280,   "below": 120},
}
COOLDOWN_SECONDS = 3600  # 1 hour between same alert
last_alert = {}

def check_prices():
    ids = ",".join(WATCHLIST.keys())
    prices = cg_get("/simple/price", {
        "ids": ids,
        "vs_currencies": "usd",
        "include_24hr_change": True
    })
    for coin, levels in WATCHLIST.items():
        price = prices[coin]["usd"]
        change = prices[coin].get("usd_24h_change", 0)
        key_above = f"{coin}_above"
        key_below = f"{coin}_below"
        now = time.time()

        if price > levels["above"]:
            if now - last_alert.get(key_above, 0) > COOLDOWN_SECONDS:
                send_alert(coin, price, change, "ABOVE", levels["above"])
                last_alert[key_above] = now

        if price < levels["below"]:
            if now - last_alert.get(key_below, 0) > COOLDOWN_SECONDS:
                send_alert(coin, price, change, "BELOW", levels["below"])
                last_alert[key_below] = now

def send_alert(coin, price, change, direction, level):
    emoji = "🚀" if direction == "ABOVE" else "📉"
    msg = MIMEText(
        f"{emoji} {coin.upper()} is {direction} ${level:,.0f}\n"
        f"Current price: ${price:,.2f}\n"
        f"24h change: {change:+.2f}%\n"
        f"Time: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
    )
    msg["Subject"] = f"[OpenClaw] {coin.upper()} Alert: {direction} ${level:,.0f}"
    msg["From"] = "alerts@yourdomain.com"
    msg["To"] = "you@example.com"
    with smtplib.SMTP("localhost") as s:
        s.send_message(msg)
    print(f"Alert sent: {coin} {direction} ${level:,.0f}")

# Run every 2 minutes (well within 30 req/min limit)
while True:
    check_prices()
    time.sleep(120)

Key design patterns:

Email Configuration

The example uses smtplib.SMTP("localhost") which assumes a local mail server. For Gmail or other providers, use the provider's SMTP host and credentials. For production, consider using a service like SendGrid or Twilio.

Multi-Coin Dashboard

Build a live updating terminal dashboard to monitor multiple coins simultaneously. This example uses the tabulate library for pretty-printed tables:

python
from tabulate import tabulate
import os

def clear():
    os.system("cls" if os.name == "nt" else "clear")

PORTFOLIO_COINS = ["bitcoin","ethereum","solana","cardano","polkadot","chainlink","avalanche-2"]

def dashboard():
    data = cg_get("/coins/markets", {
        "vs_currency": "usd",
        "ids": ",".join(PORTFOLIO_COINS),
        "order": "market_cap_desc",
        "per_page": 50,
        "page": 1,
        "sparkline": False,
        "price_change_percentage": "1h,24h,7d"
    })
    rows = []
    for c in data:
        d1h = c.get("price_change_percentage_1h_in_currency") or 0
        d24 = c.get("price_change_percentage_24h") or 0
        d7d = c.get("price_change_percentage_7d_in_currency") or 0
        rows.append([
            c["symbol"].upper(),
            f"${c['current_price']:,.4f}",
            f"{'+' if d1h>0 else ''}{d1h:.2f}%",
            f"{'+' if d24>0 else ''}{d24:.2f}%",
            f"{'+' if d7d>0 else ''}{d7d:.2f}%",
            f"${c['market_cap']/1e9:.2f}B",
        ])
    clear()
    print(f"=== OpenClaw Crypto Dashboard | {datetime.now().strftime('%H:%M:%S')} ===\n")
    print(tabulate(rows, headers=["Coin","Price","1h","24h","7d","Mkt Cap"], tablefmt="rounded_outline"))
    print("\nRefreshing in 2 min... (Ctrl+C to exit)")

while True:
    try:
        dashboard()
        time.sleep(120)
    except KeyboardInterrupt:
        print("\nDashboard stopped.")
        break

Install tabulate with pip install tabulate. This dashboard refreshes every 2 minutes, showing 1-hour, 24-hour, and 7-day price changes alongside current market cap. Perfect for monitoring a crypto portfolio.

Rate Limiting & Best Practices

CoinGecko's free API is rate-limited but generous for most use cases. Understanding these limits prevents your automation from being blocked:

Rate Limits

Free tier: 30 requests/minute. Pro Demo key: 500/minute (still free for testing). If you exceed limits, you'll get HTTP 429 (Too Many Requests) responses.

Strategies to Stay Within Limits

Handling Rate Limit Errors

Add retry logic with exponential backoff:

python
import time

def cg_get_with_retry(endpoint, params=None, max_retries=3):
    """Fetch with exponential backoff on rate limit."""
    for attempt in range(max_retries):
        try:
            resp = requests.get(f"{BASE}{endpoint}", params=params, timeout=10)
            if resp.status_code == 429:
                wait = 2 ** attempt  # 1, 2, 4 seconds
                print(f"Rate limited. Waiting {wait}s...")
                time.sleep(wait)
                continue
            resp.raise_for_status()
            return resp.json()
        except requests.RequestException as e:
            print(f"Error: {e}")
            if attempt < max_retries - 1:
                time.sleep(2 ** attempt)
    return None

CoinGecko Endpoints Reference

A quick reference table of the most useful free API endpoints:

Endpoint Description Key Parameters
/simple/price Live prices for 1+ coins (fastest) ids, vs_currencies, include_24hr_change
/coins/markets Full market data + % changes (paginated) vs_currency, order, per_page, price_change_percentage
/coins/{id}/ohlc OHLCV candles (daily or 4h), 1–90 days vs_currency, days
/coins/{id}/market_chart Price + volume + mcap history vs_currency, days, interval
/search/trending Top 7 trending coins right now none (no params required)
/global Total crypto market cap + dominance % none (no params required)

Coin IDs: Use lowercase with hyphens (e.g., bitcoin, ethereum, chainlink). Get a full list at /coins/list.

Common Use Cases

Get trending coins in real time

python
trending = cg_get("/search/trending")
for coin in trending["coins"][:7]:
    print(f"{coin['item']['name']} (#{coin['item']['market_cap_rank']})")

Get total market cap + Bitcoin dominance

python
global_data = cg_get("/global")
mcap = global_data["data"]["total_market_cap"]["usd"]
btc_dom = global_data["data"]["btc_dominance"]
print(f"Total Market Cap: ${mcap/1e12:.2f}T")
print(f"BTC Dominance: {btc_dom:.2f}%")

Get price data in multiple currencies

python
prices = cg_get("/simple/price", {
    "ids": "bitcoin,ethereum",
    "vs_currencies": "usd,eur,gbp,jpy"
})
for coin, rates in prices.items():
    print(f"{coin}: {rates}")

Next Steps

You now have the foundation for fetching live prices, historical OHLCV data, and building automated price alerts. In the next part of the series, we'll explore On-Chain Analytics — tracking wallet movements, transaction flows, and on-chain signals using APIs like Glassnode and The Graph.

Key skills to practice: