Döndürülen Proxy'lerle Bybit V5 Market API Nasıl Scrape Edilir

Bybit V5 Market API'sini döndürülen residential proxy'lerle scrape etmek için tam rehber: orderbook, tickers, kline uç noktaları, rate limit yönetimi, geo-block aşımı ve ProxyHat entegrasyonu ile çalışan kod örnekleri.

How to Scrape the Bybit V5 Market API with Rotating Proxies
Bu makalede

Döndürülen Proxy'lerle Bybit V5 Market API Nasıl Scrape Edilir: Geliştirici Rehberi

Bybit V5 Market API'sini scrape etmek, crypto trading bot'ları ve piyasa verisi mühendisleri için günlük bir ihtiyaçtır — ancak Bybit'in IP bazlı rate limitleri ve coğrafi kısıtlamaları, sürekli veri çekmeyi zorlaştırır. Döndürülen proxy'lerle Bybit V5 Market API'sini scrape etmek, tek bir IP'nin banlanmadan yüksek hacimli orderbook, ticker ve kline verisi çekmenin en pratik yoludur. Bu rehberde api.bybit.com/v5/market/ uç noktalarını, rate limit mimarisini, geo-block'ları ve ProxyHat ile nasıl güvenli bir scraping pipeline kuracağınızı adım adım göstereceğiz.

Yasal Uyarı: Bybit'in API Kullanım Şartları, public market verisinin kişisel kullanım için serbest olabileceğini ancak ticari yeniden dağıtımın kısıtlandığını belirtir. Bu rehber yalnızca eğitim amaçlıdır; Bybit'in resmi V5 API dokümantasyonunu ve Kullanım Şartlarını inceleyin. Her zaman robots.txt ve platform ToS'una uyun.

Bybit V5 Market API Uç Noktaları ve Yanıt Zarfı

Bybit'in V5 API'si, tüm public market verisini /v5/market/ altında birleştirir. Her uç nokta category parametresi alır: spot (spot), linear (USDT perpetual), inverse (inverse contracts) ve option (opsiyonlar). Tüm yanıtlar standart bir zarf içinde gelir:

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

retCode 0 ise istek başarılıdır; 0 dışındaki değerler hatayı gösterir ve retMsg açıklama içerir. Rate limit aşıldığında retCode 10001 dönebilir veya doğrudan HTTP 403 alabilirsiniz.

GET /v5/market/orderbook

Order book snapshot'ı döndürür. category (spot|linear|inverse|option), symbol ve limit (1–200) parametreleri alır. Yanıt, bids ve asks array'leri içerir; her eleman [price, size] formatındadır. Bybit V5 dokümantasyonuna göre, limit=200 için maksimum 200 seviye döner.

GET /v5/market/tickers

Belirli bir kategorideki tüm veya tek bir sembolün ticker verisini döndürür. category zorunludur; symbol opsiyoneldir (verilmezse tüm semboller döner). Spot için lastPrice, volume24h, turnover24h alanlarını içerir.

GET /v5/market/kline

Mum (candlestick) verisi döndürür. category, symbol, interval (1, 5, 15, 30, 60, 240, D, W, M) ve limit (max 200) alır. cursor parametresi ile sayfalama yapılır; yanıttaki nextPageCursor sonraki sayfaya geçiş için kullanılır. Her mum [startTime, open, high, low, close, volume, turnover] formatındadır.

GET /v5/market/recent-trade

Son işlemleri döndürür. category, symbol ve limit (max 1000) alır. Her işlem [execId, price, size, time, side] formatındadır.

IP Bazlı Rate Limitler ve ~10 Dakikalık Ban Penceresi

Bybit, rate limitleri IP bazlı uygular. Bybit V5 rate limit dokümantasyonuna göre, public market uç noktaları genellikle saniyede 5–20 istek izni verir; ancak /v5/market/orderbook gibi yoğun uç noktalarda bu sınır daha düşük olabilir. Limit aşıldığında:

  • HTTP 403 veya retCode: 10001 döner.
  • IP yaklaşık 10 dakika boyunca banlanır.
  • Ban penceresi boyunca tüm market uç noktaları bu IP için engellenir.

Bu, tek bir sunucudan orderbook scrape eden bot'lar için kritik bir sorundur. 5 saniyede 50 istek gönderirseniz, IP'niz 10 dakika boyunca banlanır ve veri akışınız kesilir. Döndürülen proxy'ler, her isteği farklı bir IP'den yaparak bu sorunu çözer.

Coğrafi Kısıtlamalar ve CloudFront Blokları

Bybit, ABD, İngiltere ve bazı diğer bölgelerde coğrafi kısıtlamalar uygular. Kısıtlı bir bölgeden API'ye erişmeye çalıştığınızda, CloudFront tabanlı bir 403 Forbidden yanıtı alırsınız — bu, API'nin retCode zarfına hiç ulaşmadan önce gerçekleşir. HTTP proxy'ler, isteği farklı bir coğrafyadan yönlendirerek bu engeli aşmanıza yardımcı olur.

ProxyHat'ın residential proxy'leri ile -country-US gibi username flag'leri kullanarak izin verilen bir bölgeden bağlanabilirsiniz. Residential IP'ler, datacenter IP'lerinden daha az tespit edilir çünkü gerçek ISP IP'lerine benzer. ProxyHat 100+ lokasyonda residential IP sunar.

Ham Proxy vs ProxyHat ile Kod Örnekleri

Aşağıda her örnek iki varyasyon gösterir: ham proxy (generic proxy URL) ve ProxyHat entegrasyonu (gate.proxyhat.com ile geo-targeting ve session flag'leri).

1. curl ile Orderbook Sorgulama

Ham proxy ile:

# Ham proxy ile Bybit orderbook
curl -x http://proxyuser:proxypass@192.168.1.100:3128 \
  "https://api.bybit.com/v5/market/orderbook?category=spot&symbol=BTCUSDT&limit=50"

ProxyHat ile (US geo-targeting):

# ProxyHat residential proxy ile US lokasyonundan
curl -x http://user-country-US:pass@gate.proxyhat.com:8080 \
  "https://api.bybit.com/v5/market/orderbook?category=spot&symbol=BTCUSDT&limit=50"

2. Node.js (axios) ile Ticker Scrape — IP Rotasyonu

Ham proxy ile (sabit IP, rate limit riski):

const axios = require('axios');
const HttpsProxyAgent = require('https-proxy-agent');

const proxyUrl = 'http://proxyuser:proxypass@192.168.1.100:3128';
const agent = new HttpsProxyAgent(proxyUrl);

async function fetchTickersRaw(symbols) {
  const results = [];
  for (const symbol of symbols) {
    try {
      const res = await axios.get(
        'https://api.bybit.com/v5/market/tickers',
        {
          params: { category: 'spot', symbol },
          httpsAgent: agent,
          timeout: 5000
        }
      );
      if (res.data.retCode === 0) {
        results.push(...res.data.result.list);
      } else {
        console.error(`API hatası: ${res.data.retCode} - ${res.data.retMsg}`);
      }
    } catch (err) {
      console.error(`İstek hatası for ${symbol}:`, err.message);
    }
  }
  return results;
}

fetchTickersRaw(['BTCUSDT', 'ETHUSDT', 'SOLUSDT']).then(console.log);

ProxyHat ile (her sembol için yeni IP):

const axios = require('axios');
const HttpsProxyAgent = require('https-proxy-agent');

// ProxyHat proxy URL builder (SDK pattern)
function proxyHatUrl(country, session) {
  let username = 'user';
  if (country) username += `-country-${country}`;
  if (session) username += `-session-${session}`;
  return `http://${username}:pass@gate.proxyhat.com:8080`;
}

async function fetchTickersProxyHat(symbols) {
  const results = [];
  for (const symbol of symbols) {
    // Her sembol için yeni residential IP (rotating)
    const agent = new HttpsProxyAgent(proxyHatUrl('US'));
    try {
      const res = await axios.get(
        'https://api.bybit.com/v5/market/tickers',
        {
          params: { category: 'spot', symbol },
          httpsAgent: agent,
          timeout: 5000
        }
      );
      if (res.data.retCode === 0) {
        results.push(...res.data.result.list);
      } else {
        console.error(`API hatası: ${res.data.retCode} - ${res.data.retMsg}`);
      }
    } catch (err) {
      console.error(`İstek hatası for ${symbol}:`, err.message);
    }
  }
  return results;
}

fetchTickersProxyHat(['BTCUSDT', 'ETHUSDT', 'SOLUSDT']).then(console.log);

3. Python ile Kline Verisi Çekme

Ham proxy ile:

import requests

proxies = {
    'http': 'http://proxyuser:proxypass@192.168.1.100:3128',
    'https': 'http://proxyuser:proxypass@192.168.1.100:3128'
}

def fetch_kline_raw(symbol, interval='60', limit=200):
    url = 'https://api.bybit.com/v5/market/kline'
    params = {
        'category': 'linear',
        'symbol': symbol,
        'interval': interval,
        'limit': limit
    }
    try:
        resp = requests.get(url, params=params, proxies=proxies, timeout=10)
        data = resp.json()
        if data.get('retCode') == 0:
            return data['result']['list']
        else:
            print(f"API hatası: {data.get('retCode')} - {data.get('retMsg')}")
            return []
    except Exception as e:
        print(f"İstek hatası: {e}")
        return []

candles = fetch_kline_raw('BTCUSDT', '60', 200)
print(f"{len(candles)} mum verisi alındı")

ProxyHat sticky session ile (kline pagination için aynı IP):

import requests
import time

def proxyhat_url(country='US', session=None):
    username = f'user-country-{country}'
    if session:
        username += f'-session-{session}'
    return f'http://{username}:pass@gate.proxyhat.com:8080'

def fetch_kline_paginated(symbol, interval='60', total=1000):
    """Sticky session ile kline pagination — aynı IP'de kalır."""
    session_id = f'kline-{symbol}-{int(time.time())}'
    proxy_url = proxyhat_url(country='US', session=session_id)
    proxies = {'http': proxy_url, 'https': proxy_url}
    
    all_candles = []
    cursor = None
    
    while len(all_candles) < total:
        url = 'https://api.bybit.com/v5/market/kline'
        params = {
            'category': 'linear',
            'symbol': symbol,
            'interval': interval,
            'limit': 200
        }
        if cursor:
            params['cursor'] = cursor
        
        try:
            resp = requests.get(url, params=params, proxies=proxies, timeout=10)
            data = resp.json()
            if data.get('retCode') == 0:
                candles = data['result']['list']
                all_candles.extend(candles)
                cursor = data['result'].get('nextPageCursor')
                if not cursor or not candles:
                    break
                time.sleep(0.2)  # Rate budgeting: ~5 req/s
            else:
                print(f"API hatası: {data.get('retCode')} - {data.get('retMsg')}")
                break
        except Exception as e:
            print(f"İstek hatası: {e}")
            break
    
    return all_candles[:total]

candles = fetch_kline_paginated('BTCUSDT', '60', 1000)
print(f"Toplam {len(candles)} mum verisi alındı")

Rate Budgeting, Retry ve Backoff Stratejileri

Production'da yalnızca IP rotasyonu yeterli değildir; her uç nokta için ayrı bir rate budget belirlemeniz gerekir. Aşağıdaki Node.js örneği, per-endpoint rate limiting, exponential backoff ve circuit breaker pattern'ini birleştirir:

const axios = require('axios');
const HttpsProxyAgent = require('https-proxy-agent');

class BybitScraper {
  constructor() {
    this.requestTimestamps = [];
    this.maxRequestsPerSecond = 5;
    this.maxRetries = 3;
    this.circuitOpen = false;
    this.failureCount = 0;
    this.failureThreshold = 5;
  }

  getProxyAgent(country = 'US', session = null) {
    let username = `user-country-${country}`;
    if (session) username += `-session-${session}`;
    return new HttpsProxyAgent(
      `http://${username}:pass@gate.proxyhat.com:8080`
    );
  }

  async rateLimit() {
    const now = Date.now();
    this.requestTimestamps = this.requestTimestamps.filter(
      ts => now - ts < 1000
    );
    if (this.requestTimestamps.length >= this.maxRequestsPerSecond) {
      const wait = 1000 - (now - this.requestTimestamps[0]);
      await new Promise(r => setTimeout(r, wait));
    }
    this.requestTimestamps.push(Date.now());
  }

  async request(endpoint, params, retries = 0) {
    if (this.circuitOpen) {
      throw new Error('Circuit breaker açık — 30s sonra tekrar deneyin');
    }
    await this.rateLimit();
    const agent = this.getProxyAgent('US');
    
    try {
      const res = await axios.get(
        `https://api.bybit.com/v5/market/${endpoint}`,
        { params, httpsAgent: agent, timeout: 10000 }
      );
      
      if (res.data.retCode === 0) {
        this.failureCount = 0;
        return res.data.result;
      }
      
      // Rate limit hatası — backoff ile tekrar dene
      if (res.data.retCode === 10001 && retries < this.maxRetries) {
        const backoff = Math.pow(2, retries) * 1000;
        console.log(`Rate limit hit, ${backoff}ms bekleniyor...`);
        await new Promise(r => setTimeout(r, backoff));
        return this.request(endpoint, params, retries + 1);
      }
      
      throw new Error(`API: ${res.data.retCode} - ${res.data.retMsg}`);
    } catch (err) {
      this.failureCount++;
      if (this.failureCount >= this.failureThreshold) {
        this.circuitOpen = true;
        setTimeout(() => {
          this.circuitOpen = false;
          this.failureCount = 0;
        }, 30000);
      }
      if (retries < this.maxRetries) {
        const backoff = Math.pow(2, retries) * 1000;
        console.log(`Hata: ${err.message}, ${backoff}ms sonra tekrar...`);
        await new Promise(r => setTimeout(r, backoff));
        return this.request(endpoint, params, retries + 1);
      }
      throw err;
    }
  }

  async scrapeOrderbook(symbols) {
    const results = {};
    for (const symbol of symbols) {
      try {
        const data = await this.request('orderbook', {
          category: 'spot',
          symbol,
          limit: 50
        });
        results[symbol] = data;
        console.log(`${symbol}: ${data.bids.length} bid, ${data.asks.length} ask`);
      } catch (err) {
        console.error(`${symbol} başarısız: ${err.message}`);
      }
    }
    return results;
  }
}

const scraper = new BybitScraper();
scraper.scrapeOrderbook(['BTCUSDT', 'ETHUSDT', 'SOLUSDT', 'XRPUSDT'])
  .then(() => console.log('Tamamlandı'));

Sticky Session'lar ile Kline Pagination

Bybit kline endpoint'i cursor tabanlı sayfalama kullanır. Eğer her istekte IP döndürürseniz, cursor tutarsız olabilir veya Bybit şüpheli davranış olarak işaretleyebilir. ProxyHat'ın -session-abc123 flag'i ile belirli bir süre boyunca aynı IP'de kalabilirsiniz. Bu, pagination boyunca tutarlı bir bağlantı sağlar ve rate limit bütçenizi tek bir IP üzerinde yönetmenize olanak tanır.

Yukarıdaki Python örneğinde session_id parametresi ile sticky session kullanılmıştır. Pagination tamamlandığında yeni bir session_id ile farklı bir IP'ye geçebilirsiniz.

REST Snapshot vs WebSocket Orderbook

REST ile orderbook çekmek her istekte ~200ms gecikme üretir ve rate limit tüketir. Sürekli depth takibi için WebSocket çok daha verimlidir:

ÖzellikREST /v5/market/orderbookWebSocket orderbook.50
Latens~200ms per istek~50ms push (artımlı)
Rate limit~5 req/s (IP bazlı)1 bağlantı, sınırsız push
Veri tazeliğiSnapshot (anlık)Artımlı güncelleme
KullanımTek seferlik sorguSürekli monitoring
KarmaşıklıkDüşükOrta (reconnect/replay)

WebSocket ile ProxyHat SOCKS5 proxy üzerinden orderbook.50 stream'ine abone olabilirsiniz:

const WebSocket = require('ws');
const { SocksProxyAgent } = require('socks-proxy-agent');

// ProxyHat SOCKS5 proxy ile US residential IP
const agent = new SocksProxyAgent(
  'socks5://user-country-US:pass@gate.proxyhat.com:1080'
);

const ws = new WebSocket(
  'wss://stream.bybit.com/v5/public/spot',
  { agent }
);

ws.on('open', () => {
  ws.send(JSON.stringify({
    op: 'subscribe',
    args: ['orderbook.50.BTCUSDT']
  }));
  console.log('orderbook.50.BTCUSDT aboneliği aktif');
});

ws.on('message', (data) => {
  const msg = JSON.parse(data.toString());
  if (msg.topic && msg.topic.startsWith('orderbook')) {
    const { bids, asks } = msg.data;
    console.log(`Depth: ${bids.length} bid, ${asks.length} ask`);
  }
});

ws.on('error', (err) => console.error('WS hata:', err.message));
ws.on('close', () => console.log('WS kapandı — reconnect gerekli'));

WebSocket kullanırken dikkat edin: bağlantı kopması durumunda snapshot almanız gerekir (REST ile /v5/market/orderbook çağırıp mevcut durumu senkronize edin). Bybit WebSocket protokolü, reconnect sonrası snapshot ve sonrasındaki delta mesajlarını gönderir.

Önemli Çıkarımlar

  • IP rotasyonu şart: Bybit'in IP bazlı rate limitleri ve ~10 dakikalık ban penceresi, tek IP'den yüksek hacimli scrape'i imkansız kılar. Her istekte yeni IP kullanın.
  • Residential proxy tercih edin: Datacenter IP'leri CloudFront tarafından tespit edilip 403 dönebilir. ProxyHat residential IP'leri ile -country-US flag'i kullanın.
  • Sticky session pagination için: Kline cursor pagination'da -session-abc123 ile aynı IP'de kalın; pagination bitince yeni session'a geçin.
  • Rate budgeting uygulayın: Döndürülen proxy kullansanız bile saniyede maksimum 5 istek ile kendinizi sınırlayın.
  • WebSocket tercih edin: Sürekli orderbook takibi için REST yerine WebSocket orderbook.50 stream'ini kullanın; 10x daha düşük latens ve rate limit tasarrufu sağlar.
  • retCode kontrolü yapın: Her yanıtta retCode === 0 kontrolü yapın; 10001 rate limit, diğer kodlar farklı hatalar anlamına gelir.

ProxyHat ile residential proxy'lere erişmek için fiyatlandırma sayfasını inceleyin. Web scraping use case sayfamızda daha fazla örnek bulabilirsiniz. Detaylı proxy yapılandırması için ProxyHat dokümantasyonuna bakın.

Sık sorulan sorular

Bybit V5 Market API'sini döndürülen proxy'lerle scrape etmek nedir?

Bybit'in /v5/market/ uç noktalarından (orderbook, tickers, kline, recent-trade) her istekte farklı bir IP kullanarak veri çekme yöntemidir. Bu, tek bir IP'nin rate limit'e takılmasını veya ~10 dakika banlanmasını önler ve coğrafi kısıtlamaları residential proxy'ler ile aşmanıza yardımcı olur.

Bybit V5 Market API scrape için hangi proxy tipi en iyidir?

Residential proxy'ler en iyi sonucu verir çünkü Bybit'in CloudFront tabanlı geo-filtrelemesi datacenter IP'lerini tespit edip 403 dönebilir. ProxyHat'ın gate.proxyhat.com:8080 uç noktası üzerinden -country-US formatında residential IP'ler kullanabilirsiniz. SOCKS5 için 1080 portunu kullanın.

Bybit API'de ban penceresi ne kadar sürer?

Bybit, rate limit ihlallerinde IP'yi yaklaşık 10 dakika boyunca banlar. Bu süre zarfında uç nokta 403 veya retCode 10001 döndürür. Döndürülen proxy'ler ile her isteği farklı bir IP'den yaparak bu ban penceresinden etkilenmeden veri çekmeye devam edebilirsiniz.

Bybit V5 Market API'de sticky session ne zaman kullanılmalı?

Kline pagination gibi cursor-tabanlı sayfalama işlemlerinde, aynı IP'de kalmak tutarlı veri akışı sağlar ve Bybit'in şüpheli davranış algılamasını azaltır. ProxyHat'ın -session-abc123 flag'i ile belirli bir süre boyunca aynı IP'yi tutabilir, pagination tamamlandığında yeni session'a geçebilirsiniz.

Bybit API scrape ederken 403 hatası alıyorum, ne yapmalıyım?

403 genellikle coğrafi kısıtlama veya rate limit ihlali anlamına gelir. Önce ProxyHat ile -country-US gibi bir geo-targeting flag'i kullanarak izin verilen bir bölgeden residential IP ile bağlanmayı deneyin. Ardından rate budgeting ile saniyede maksimum 5 istekle sınırlayın ve exponential backoff uygulayın.

Başlamaya hazır mısınız?

148'den fazla ülkede residential, ISP ve mobil proxy'ler. Ücretsiz hesap oluşturun.

Ücretsiz hesap oluştur
← Bloga Dön