Come Scrape la Bybit V5 Market API con Proxy Rotanti: Guida per Sviluppatori

Guida pratica per sviluppatori su come scrapeare gli endpoint pubblici /v5/market/ di Bybit con proxy rotanti ProxyHat. Esempi in Node.js e Python, gestione dei rate limit e geo-restrizioni.

How to Scrape the Bybit V5 Market API with Rotating Proxies
In questo articolo

Se stai costruendo un bot di trading o un sistema di monitoraggio dei dati di mercato su Bybit, prima o poi ti scontri con i limiti di frequenza IP e i blocchi geografici di CloudFront. In questa guida spieghiamo come scrapeare la Bybit V5 Market API con proxy rotanti, coprendo gli endpoint pubblici /v5/market/, il modello di rate limiting di Bybit e come i proxy residenziali ProxyHat ripristinano l'accesso da paesi consentiti.

Avviso legale: gli endpoint pubblici di mercato di Bybit restituiscono dati di dominio pubblico, ma devi rispettare i Termini di Servizio (ToS) di Bybit e il file robots.txt. Non fare scraping di dati privati o autenticati senza autorizzazione. Consulta i Termini di Servizio di Bybit prima di avviare qualsiasi progetto.

Come Scrapeare la Bybit V5 Market API con Proxy Rotanti: panoramica

La V5 Market API di Bybit è l'interfaccia REST pubblica per orderbook, ticker, candele (kline) e trade recenti. È un'API unificata che copre spot, derivati lineari, opzioni e futures inversi tramite il parametro category. A differenza delle API private, non richiede chiavi API, ma è soggetta a rigidi rate limit per IP e a restrizioni geografiche.

Scrapearla in modo affidabile richiede tre cose: capire la struttura della risposta retCode/retMsg, gestire i limiti di frequenza per-endpoint e usare proxy rotanti per distribuire le richieste su più IP. I proxy residenziali di ProxyHat (accessibili via gate.proxyhat.com:8080 per HTTP e :1080 per SOCKS5) sono particolarmente efficaci perché usano IP ISP reali, riducendo il rischio di blocchi CloudFront.

Endpoint pubblici sotto /v5/market/

La V5 Market API espone quattro endpoint pubblici principali. Ognuno accetta il parametro category (spot, linear, inverse, option) e restituisce un envelope JSON standard con i campi retCode e retMsg.

EndpointScopoParametri chiaveRate limit tipico
GET /v5/market/orderbookSnapshot dell'orderbookcategory, symbol, limit (depth)~50 req/s per IP
GET /v5/market/tickersTicker di mercato (prezzo, volume, funding)category, symbol (opzionale)~10 req/s per IP
GET /v5/market/klineCandele storichecategory, symbol, interval, start, end, limit~10 req/s per IP
GET /v5/market/recent-tradeTrade recenticategory, symbol, limit~20 req/s per IP

L'envelope di risposta retCode/retMsg

Ogni risposta V5 segue lo stesso schema:

{
  "retCode": 0,
  "retMsg": "OK",
  "result": { ... },
  "time": 1700000000000
}

Un retCode pari a 0 indica successo. Qualsiasi altro valore indica un errore: 10001 per parametri invalidi, 10010 per rate limit, 403- stile per blocchi regionali. Il campo retMsg fornisce una descrizione leggibile. Il tuo codice deve sempre controllare retCode prima di processare result.

Esempio base con curl (senza proxy)

curl -s 'https://api.bybit.com/v5/market/orderbook?category=spot&symbol=BTCUSDT&limit=50' | jq .

Rate limit IP e finestra di ban di 10 minuti

Bybit applica rate limit per-endpoint su base IP. Quando superi il limite, ricevi un HTTP 403 o un retCode di errore. Il problema critico è che Bybit può mettere al bando un IP per circa 10 minuti se i burst sono troppo aggressivi, specialmente su /v5/market/orderbook che ha un limite più alto (~50 req/s) ma è il più colpito dai bot.

Secondo la documentazione ufficiale sui rate limit di Bybit V5, i limiti sono dinamici e possono cambiare in base al carico. Una strategia di scraping robusta deve:

  • Rispettare un budget per-endpoint inferiore al limite dichiarato (es. 80% del limite).
  • Usare backoff esponenziale sui 403/429.
  • Rotare gli IP per distribuire il carico e ridurre il rischio di ban.

Geo-restrizioni: blocchi 403 e CloudFront

Bybit blocca l'accesso da Stati Uniti, Regno Unito e altre regioni regolamentate. Se il tuo IP è in una zona bloccata, ricevi un 403 da CloudFront o una pagina di blocco invece del JSON. Questo è un problema serio per sviluppatori in US/UK che vogliono accedere ai dati di mercato pubblici.

I proxy residenziali ProxyHat risolvono questo problema instradando le richieste tramite IP ISP di paesi consentiti (es. Germania, Singapore, Giappone). Usando il geo-targeting nel username con il formato -country-XX, puoi forzare l'uscita da un paese specifico:

curl -x http://user-country-DE:pass@gate.proxyhat.com:8080 \
  'https://api.bybit.com/v5/market/tickers?category=spot'

Consulta la pagina delle locazioni ProxyHat per la lista completa di paesi supportati.

Setup ProxyHat: proxy raw vs SDK

ProxyHat espone un gateway HTTP su gate.proxyhat.com:8080 e SOCKS5 su :1080. Le opzioni di rotazione e geo-targeting vanno nel username. Ecco i formati:

  • Rotazione per-request: http://USERNAME:PASSWORD@gate.proxyhat.com:8080
  • Geo-targeting paese: http://USERNAME-country-DE:PASSWORD@gate.proxyhat.com:8080
  • Sticky session: http://USERNAME-session-abc123:PASSWORD@gate.proxyhat.com:8080
  • SOCKS5: socks5://USERNAME:PASSWORD@gate.proxyhat.com:1080

Per dettagli completi, consulta la documentazione ProxyHat.

Esempio Node.js (axios): rotazione IP su lista di symbol

Questo esempio usa il proxy raw di ProxyHat per scrapeare i ticker di una lista di symbol, con rotazione IP per-request, retry con backoff e budget di rate.

const axios = require('axios');

const PROXY_USER = 'user';
const PROXY_PASS = 'pass';
const PROXY_HOST = 'gate.proxyhat.com';
const PROXY_PORT = 8080;

const symbols = ['BTCUSDT', 'ETHUSDT', 'SOLUSDT', 'XRPUSDT', 'DOGEUSDT'];
const BASE_URL = 'https://api.bybit.com';

// Genera un session ID unico per rotazione per-request
function randomSession() {
  return Math.random().toString(36).substring(2, 12);
}

async function fetchTicker(symbol, attempt = 1) {
  const sessionId = randomSession();
  const proxyUrl = `http://${PROXY_USER}-country-DE-session-${sessionId}:${PROXY_PASS}@${PROXY_HOST}:${PROXY_PORT}`;

  try {
    const res = await axios.get(`${BASE_URL}/v5/market/tickers`, {
      params: { category: 'spot', symbol },
      proxy: { host: PROXY_HOST, port: PROXY_PORT, auth: { username: `${PROXY_USER}-country-DE-session-${sessionId}`, password: PROXY_PASS } },
      timeout: 10000,
    });

    if (res.data.retCode !== 0) {
      throw new Error(`Bybit error ${res.data.retCode}: ${res.data.retMsg}`);
    }
    return res.data.result;
  } catch (err) {
    if (attempt < 4) {
      const backoff = Math.pow(2, attempt) * 500;
      console.error(`Retry ${symbol} in ${backoff}ms: ${err.message}`);
      await new Promise(r => setTimeout(r, backoff));
      return fetchTicker(symbol, attempt + 1);
    }
    throw err;
  }
}

async function main() {
  const results = [];
  // Rate budget: 8 req/s (sotto il limite ~10 req/s)
  for (const sym of symbols) {
    const data = await fetchTicker(sym);
    results.push(data);
    await new Promise(r => setTimeout(r, 125)); // 125ms = 8 req/s
  }
  console.log(JSON.stringify(results, null, 2));
}

main().catch(console.error);

Versione con ProxyHat SDK (Node.js)

const { ProxyHatClient } = require('@proxyhat/sdk');
const axios = require('axios');

const ph = new ProxyHatClient({
  username: 'user',
  password: 'pass',
  country: 'DE',
  rotate: true, // rotazione per-request
});

async function fetchTickerSDK(symbol, attempt = 1) {
  const proxyConfig = await ph.getProxyConfig(); // {host, port, auth}

  try {
    const res = await axios.get('https://api.bybit.com/v5/market/tickers', {
      params: { category: 'spot', symbol },
      proxy: { host: proxyConfig.host, port: proxyConfig.port, auth: proxyConfig.auth },
      timeout: 10000,
    });

    if (res.data.retCode !== 0) {
      throw new Error(`Bybit ${res.data.retCode}: ${res.data.retMsg}`);
    }
    return res.data.result;
  } catch (err) {
    if (attempt < 4) {
      await new Promise(r => setTimeout(r, Math.pow(2, attempt) * 500));
      return fetchTickerSDK(symbol, attempt + 1);
    }
    throw err;
  }
}

async function main() {
  const symbols = ['BTCUSDT', 'ETHUSDT', 'SOLUSDT'];
  for (const s of symbols) {
    const r = await fetchTickerSDK(s);
    console.log(s, r.list[0].lastPrice);
    await new Promise(r => setTimeout(r, 125));
  }
}

main();

Esempio Python: orderbook con proxy rotanti

import requests
import time
import random
import string

PROXY_USER = 'user'
PROXY_PASS = 'pass'
PROXY_HOST = 'gate.proxyhat.com'
PROXY_PORT = 8080
BASE_URL = 'https://api.bybit.com'

def random_session():
    return ''.join(random.choices(string.ascii_lowercase + string.digits, k=10))

def fetch_orderbook(symbol, category='linear', limit=50, attempt=1):
    session_id = random_session()
    proxy_url = f'http://{PROXY_USER}-country-DE-session-{session_id}:{PROXY_PASS}@{PROXY_HOST}:{PROXY_PORT}'
    proxies = {'http': proxy_url, 'https': proxy_url}

    try:
        res = requests.get(
            f'{BASE_URL}/v5/market/orderbook',
            params={'category': category, 'symbol': symbol, 'limit': limit},
            proxies=proxies,
            timeout=10,
        )
        res.raise_for_status()
        data = res.json()
        if data['retCode'] != 0:
            raise Exception(f"Bybit error {data['retCode']}: {data['retMsg']}")
        return data['result']
    except Exception as e:
        if attempt < 4:
            backoff = 2 ** attempt * 0.5
            print(f'Retry {symbol} in {backoff}s: {e}')
            time.sleep(backoff)
            return fetch_orderbook(symbol, category, limit, attempt + 1)
        raise

def main():
    symbols = ['BTCUSDT', 'ETHUSDT', 'SOLUSDT']
    for sym in symbols:
        ob = fetch_orderbook(sym)
        print(f'{sym}: bid={ob["b"][0][0]}, ask={ob["a"][0][0]}')
        time.sleep(0.05)  # 20 req/s budget, sotto il limite ~50

if __name__ == '__main__':
    main()

Versione Python con ProxyHat SDK

from proxyhat import ProxyHatClient
import requests
import time

ph = ProxyHatClient(username='user', password='pass', country='DE', rotate=True)

def fetch_orderbook_sdk(symbol, category='linear', limit=50, attempt=1):
    proxy_cfg = ph.get_proxy_config()  # {'host':..., 'port':..., 'auth':...}
    proxy_url = f"http://{proxy_cfg['auth']['username']}:{proxy_cfg['auth']['password']}@{proxy_cfg['host']}:{proxy_cfg['port']}"
    proxies = {'http': proxy_url, 'https': proxy_url}

    try:
        res = requests.get(
            'https://api.bybit.com/v5/market/orderbook',
            params={'category': category, 'symbol': symbol, 'limit': limit},
            proxies=proxies,
            timeout=10,
        )
        data = res.json()
        if data['retCode'] != 0:
            raise Exception(f"Bybit {data['retCode']}: {data['retMsg']}")
        return data['result']
    except Exception as e:
        if attempt < 4:
            time.sleep(2 ** attempt * 0.5)
            return fetch_orderbook_sdk(symbol, category, limit, attempt + 1)
        raise

for sym in ['BTCUSDT', 'ETHUSDT']:
    ob = fetch_orderbook_sdk(sym)
    print(sym, ob['b'][0][0], ob['a'][0][0])
    time.sleep(0.05)

Sticky session per paginazione kline

Quando scarichi dati kline storici in pagine successive, conviene mantenere lo stesso IP per tutta la sessione per evitare di saltare intervalli a causa di rotazioni. Usa il flag -session-abc123 nel username ProxyHat.

import requests
import time

PROXY_USER = 'user'
PROXY_PASS = 'pass'
SESSION_ID = 'kline-btc-001'

proxy_url = f'http://{PROXY_USER}-country-DE-session-{SESSION_ID}:{PROXY_PASS}@gate.proxyhat.com:8080'
proxies = {'http': proxy_url, 'https': proxy_url}

def fetch_kline(symbol, interval='60', start=None, end=None, limit=200):
    params = {'category': 'linear', 'symbol': symbol, 'interval': interval, 'limit': limit}
    if start:
        params['start'] = start
    if end:
        params['end'] = end

    res = requests.get(
        'https://api.bybit.com/v5/market/kline',
        params=params,
        proxies=proxies,
        timeout=10,
    )
    data = res.json()
    if data['retCode'] != 0:
        raise Exception(f"Bybit {data['retCode']}: {data['retMsg']}")
    return data['result']

def scrape_all_klines(symbol, interval='60', total_candles=1000):
    all_candles = []
    batch = 200
    end = None

    while len(all_candles) < total_candles:
        result = fetch_kline(symbol, interval=interval, end=end, limit=batch)
        candles = result['list']
        if not candles:
            break
        all_candles.extend(candles)
        # Usa il timestamp più vecchio come nuovo 'end'
        end = int(candles[-1][0]) - 1
        time.sleep(0.1)  # 10 req/s budget

    return all_candles

candles = scrape_all_klines('BTCUSDT', interval='60', total_candles=1000)
print(f'Recuperate {len(candles)} candele')

REST snapshot vs WebSocket orderbook.50

L'endpoint REST /v5/market/orderbook fornisce uno snapshot istantaneo, ma per dati live ad alta frequenza conviene usare il WebSocket pubblico di Bybit con il topic orderbook.50.{symbol}, che invia aggiornamenti incrementali a ~50ms di latenza.

AspettoREST orderbookWebSocket orderbook.50
Latenza~100-300ms per richiesta~50ms push
Rate limit~50 req/s per IP1 connessione, push continuo
Uso tipicoSnapshot periodici, backfillFeed live per bot HFT
Proxy necessario?Sì, per geo-sbypassSì, anche WS passa per proxy

Per il WebSocket, puoi configurare il proxy a livello di client (es. HttpsProxyAgent in Node.js o websockets con proxy in Python). Il gateway ProxyHat supporta connessioni WebSocket tunneling via HTTP CONNECT.

Errori comuni e edge case

  • Non controllare retCode: una risposta HTTP 200 con retCode != 0 è comunque un errore.
  • Burst su orderbook: anche se il limite è ~50 req/s, burst continui possono innescare ban di 10 minuti.
  • Geo-blocco silenzioso: CloudFront può restituire 403 senza un corpo JSON leggibile. Controlla il Content-Type.
  • Parametro category mancante: senza category, l'API restituisce errore. Ogni endpoint lo richiede.
  • Timestamp in ms: Bybit usa timestamp in millisecondi, non secondi. Per paginazione kline, usa ms.

Per iniziare con ProxyHat, consulta la pagina dei prezzi e i casi d'uso per il web scraping e il SERP tracking. Per la lista dei paesi supportati per il geo-targeting, visita locazioni.

Punti chiave (Key Takeaways)

  • La V5 Market API di Bybit usa un envelope retCode/retMsg: controlla sempre retCode == 0 prima di processare result.
  • I rate limit sono per-endpoint e per-IP: l'orderbook ha il limite più alto (~50 req/s) ma i burst possono causare ban di ~10 minuti.
  • Bybit blocca US/UK e altre regioni via CloudFront: i proxy residenziali ProxyHat con geo-targeting -country-XX ripristinano l'accesso.
  • Usa sticky session (-session-abc123) per operazioni che richiedono stato (paginazione kline) e rotazione per-request per scraping distribuito.
  • Per dati live ad alta frequenza, preferisci il WebSocket orderbook.50 al REST polling.
  • Mantieni un budget di rate dell'80% del limite dichiarato e usa backoff esponenziale sui 403/429.

FAQ

Come si scrapearla la Bybit V5 Market API con proxy rotanti?

Si inviano richieste agli endpoint pubblici /v5/market/ (orderbook, tickers, kline, recent-trade) tramite un gateway proxy rotante come ProxyHat, che assegna un IP residenziale diverso per ogni richiesta o sessione. Il proxy va configurato nel client HTTP (axios, requests) usando l'URL http://USERNAME:PASSWORD@gate.proxyhat.com:8080, con geo-targeting via -country-XX per evitare blocchi regionali.

Perché i proxy rotanti importano per il scraping della Bybit V5 Market API?

Bybit applica rate limit rigorosi per IP e ban di circa 10 minuti per burst eccessivi. Senza rotazione, un singolo IP viene rapidamente bloccato, interrompendo la raccolta dati. I proxy rotanti distribuiscono le richieste su centinaia di IP residenziali, riducendo il carico per-IP sotto la soglia di rate limit e mantenendo throughput elevato.

Quale tipo di proxy funziona meglio per scrapearla Bybit V5 Market API?

I proxy residenziali sono i più efficaci perché usano IP ISP reali, meno inclini a blocchi CloudFront e filtri anti-bot rispetto ai datacenter. Per il geo-sbypass (US/UK), il geo-targeting paese (-country-DE) è essenziale. I proxy datacenter possono funzionare per carichi leggeri ma hanno tassi di blocco più alti su Bybit.

Come evitare i blocchi nello scraping della Bybit V5 Market API?

Mantieni un budget di rate sotto il limite dichiarato (es. 80%), usa backoff esponenziale sui 403/429, ruota gli IP per-request con ProxyHat, implementa sticky session per operazioni con stato, e monitora il campo retCode per rilevare errori di rate limit prima che diventino ban. Evita burst continui su /v5/market/orderbook, l'endpoint più sensibile.

Qual è la differenza tra REST orderbook e WebSocket orderbook.50?

L'endpoint REST /v5/market/orderbook fornisce snapshot su richiesta con latenza ~100-300ms, ideale per backfill e polling periodico. Il WebSocket orderbook.50.{symbol} invia aggiornamenti incrementali push a ~50ms, ideale per bot live e HFT. Per dati real-time, il WebSocket è superiore; per snapshot storici, il REST è più semplice.

Domande frequenti

Come si scrapearla la Bybit V5 Market API con proxy rotanti?

Si inviano richieste agli endpoint pubblici /v5/market/ (orderbook, tickers, kline, recent-trade) tramite un gateway proxy rotante come ProxyHat, che assegna un IP residenziale diverso per ogni richiesta o sessione. Il proxy va configurato nel client HTTP usando l'URL http://USERNAME:PASSWORD@gate.proxyhat.com:8080, con geo-targeting via -country-XX per evitare blocchi regionali.

Perché i proxy rotanti importano per il scraping della Bybit V5 Market API?

Bybit applica rate limit rigorosi per IP e ban di circa 10 minuti per burst eccessivi. Senza rotazione, un singolo IP viene rapidamente bloccato, interrompendo la raccolta dati. I proxy rotanti distribuiscono le richieste su centinaia di IP residenziali, riducendo il carico per-IP sotto la soglia di rate limit e mantenendo throughput elevato.

Quale tipo di proxy funziona meglio per scrapearla Bybit V5 Market API?

I proxy residenziali sono i più efficaci perché usano IP ISP reali, meno inclini a blocchi CloudFront e filtri anti-bot rispetto ai datacenter. Per il geo-sbypass (US/UK), il geo-targeting paese (-country-DE) è essenziale. I proxy datacenter possono funzionare per carichi leggeri ma hanno tassi di blocco più alti su Bybit.

Come evitare i blocchi nello scraping della Bybit V5 Market API?

Mantieni un budget di rate sotto il limite dichiarato (es. 80%), usa backoff esponenziale sui 403/429, ruota gli IP per-request con ProxyHat, implementa sticky session per operazioni con stato, e monitora il campo retCode per rilevare errori di rate limit prima che diventino ban. Evita burst continui su /v5/market/orderbook, l'endpoint più sensibile.

Qual è la differenza tra REST orderbook e WebSocket orderbook.50?

L'endpoint REST /v5/market/orderbook fornisce snapshot su richiesta con latenza ~100-300ms, ideale per backfill e polling periodico. Il WebSocket orderbook.50 invia aggiornamenti incrementali push a ~50ms, ideale per bot live e HFT. Per dati real-time, il WebSocket è superiore; per snapshot storici, il REST è più semplice.

Verifica la tua configurazione proxy in pochi secondi

Verificatore di proxy gratuito — conferma che i tuoi IP siano veloci, anonimi e non bloccati.

Controlla i proxy gratis
← Torna al Blog