[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"blog-post-pt-como-raspar-bybit-v5-market-api-proxies":3},{"success":4,"payload":5,"related":63,"errors":127},true,{"id":6,"slug":7,"title":8,"excerpt":9,"body_html":10,"meta_title":11,"meta_description":12,"canonical_url":13,"canonical_override":14,"og_title":15,"og_description":12,"og_image_url":16,"faq_json":17,"key_takeaways":14,"allow_index":4,"noindex_google_only":30,"allow_follow":4,"published_at":31,"updated_at":31,"content_updated_at":32,"featured_image_url":33,"featured_image_alt":34,"card_image_url":35,"reading_time_minutes":36,"author":37,"categories":41,"tags":48,"alternates":49,"locale_paths":60,"views":62},195,"como-raspar-bybit-v5-market-api-proxies","Como coletar dados de mercado cripto com proxies rotativos (exemplo: Bybit V5 Market API)","Guia prático para desenvolvedores sobre como raspar os endpoints públicos \u002Fv5\u002Fmarket da Bybit com proxies residenciais rotativos via ProxyHat, incluindo rate limits, geo-restrições e WebSocket.","\u003Cp>Raspar a Bybit V5 Market API é tentador para bots de trading e pipelines de dados de cripto: os endpoints públicos de orderbook, tickers e klines não exigem autenticação e respondem em poucas dezenas de milissegundos. O problema aparece quando você passa de algumas requisições de teste para centenas de símbolos em loop — a Bybit impõe limites rigorosos por IP, bloqueia regiões inteiras via CloudFront e pode banir seu endereço por ~10 minutos. Neste guia você vai aprender como raspar a Bybit V5 Market API com proxies rotativos usando o gateway \u003Ccode>gate.proxyhat.com\u003C\u002Fcode>, com exemplos em Python e Node.js, sessões sticky para paginação de klines e fallback para WebSocket.\u003C\u002Fp>\n\n\u003Cblockquote>\u003Cstrong>Aviso legal:\u003C\u002Fstrong> Este guia cobre apenas endpoints públicos de dados de mercado da Bybit (\u003Ccode>\u002Fv5\u002Fmarket\u002F*\u003C\u002Fcode>). Sempre consulte os Termos de Serviço da Bybit e respeite \u003Ccode>robots.txt\u003C\u002Fcode> antes de coletar dados em escala. Não incentivamos scraping de endpoints autenticados, de conta ou de trading.\u003C\u002Fblockquote>\n\n\u003Ch2>Por que raspar a Bybit V5 Market API com proxies rotativos é necessário\u003C\u002Fh2>\n\n\u003Cp>A V5 é a API unificada da Bybit, documentada em docs.bybit.com\u002Fv5\u002Fmarket. Ela substitui as antigas v2\u002Fv3 e unifica spot, linear e option sob o parâmetro \u003Ccode>category\u003C\u002Fcode>. O domínio público é \u003Ccode>api.bybit.com\u003C\u002Fcode>, servido atrás da AWS CloudFront, o que significa que bloqueios geo aparecem como \u003Cstrong>403 Forbidden\u003C\u002Fstrong> antes mesmo de chegar à aplicação.\u003C\u002Fp>\n\n\u003Cp>Existem dois motivos principais para usar proxies ao raspar a Bybit:\u003C\u002Fp>\n\n\u003Cul>\n\u003Cli>\u003Cstrong>Rate limits por IP:\u003C\u002Fstrong> Cada endpoint tem um teto de requisições por segundo por IP de origem. Estourar repetidamente gera \u003Ccode>403\u003C\u002Fcode> e uma janela de ban de ~10 minutos.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Geo-restrições:\u003C\u002Fstrong> A Bybit bloqueia usuários em regiões restritas (EUA, Reino Unido, Canadá, Singapura, entre outras). Sem um IP de país permitido, a CloudFront devolve 403 sem corpo JSON.\u003C\u002Fli>\n\u003C\u002Ful>\n\n\u003Cp>Com \u003Ca href=\"\u002Fpt\u002Fproxy\u002Fresidential\">proxies residenciais\u003C\u002Fa> rotativos do ProxyHat, cada requisição (ou cada sessão) sai de um IP diferente localizado em um país permitido, contornando ambos os problemas de forma elegante.\u003C\u002Fp>\n\n\u003Ch3>Mapa dos endpoints públicos \u002Fv5\u002Fmarket\u003C\u002Fh3>\n\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\u003Cth>Endpoint\u003C\u002Fth>\u003Cth>Uso\u003C\u002Fth>\u003Cth>Params obrigatórios\u003C\u002Fth>\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\n\u003Ctr>\u003Ctd>\u003Ccode>GET \u002Fv5\u002Fmarket\u002Forderbook\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>Snapshot de livro de ofertas\u003C\u002Ftd>\u003Ctd>\u003Ccode>category\u003C\u002Fcode>, \u003Ccode>symbol\u003C\u002Fcode>\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>\u003Ccode>GET \u002Fv5\u002Fmarket\u002Ftickers\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>Cotação atual de um ou todos os símbolos\u003C\u002Ftd>\u003Ctd>\u003Ccode>category\u003C\u002Fcode>\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>\u003Ccode>GET \u002Fv5\u002Fmarket\u002Fkline\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>Velas OHLCV históricas\u003C\u002Ftd>\u003Ctd>\u003Ccode>category\u003C\u002Fcode>, \u003Ccode>symbol\u003C\u002Fcode>, \u003Ccode>interval\u003C\u002Fcode>\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>\u003Ccode>GET \u002Fv5\u002Fmarket\u002Frecent-trade\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>Trades recentes\u003C\u002Ftd>\u003Ctd>\u003Ccode>category\u003C\u002Fcode>, \u003Ccode>symbol\u003C\u002Fcode>\u003C\u002Ftd>\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\n\n\u003Cp>Todos retornam o envelope padrão:\u003C\u002Fp>\n\n\u003Cpre>\u003Ccode>{\n  &quot;retCode&quot;: 0,\n  &quot;retMsg&quot;: &quot;OK&quot;,\n  &quot;result&quot;: { ... },\n  &quot;time&quot;: 1700000000000\n}\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Cp>\u003Ccode>retCode: 0\u003C\u002Fcode> indica sucesso. Qualquer valor diferente (ex.: \u003Ccode>10001\u003C\u002Fcode> para parâmetro inválido, \u003Ccode>403\u003C\u002Fcode> para bloqueio) exige tratamento explícito. Veja a lista oficial de códigos de erro.\u003C\u002Fp>\n\n\u003Ch2>Rate limits da Bybit: como o \u002Fv5\u002Fmarket\u002Forderbook derruba seu IP\u003C\u002Fh2>\n\n\u003Cp>A Bybit aplica limites por endpoint e por IP de origem. Para dados públicos de mercado, os limites típicos são:\u003C\u002Fp>\n\n\u003Cul>\n\u003Cli>\u003Cstrong>Orderbook:\u003C\u002Fstrong> ~50 requisições\u002Fseg por IP (categoria spot\u002Flinear).\u003C\u002Fli>\n\u003Cli>Tickers: ~10 req\u002Fs por IP.\u003C\u002Fli>\n\u003Cli>Kline: ~10 req\u002Fs por IP.\u003C\u002Fli>\n\u003Cli>Recent-trade: ~20 req\u002Fs por IP.\u003C\u002Fli>\n\u003C\u002Ful>\n\n\u003Cp>Esses números mudam — confirme sempre na documentação oficial. O ponto crítico é o orderbook: em bots de market-making que fazem polling agressivo de profundidade, é trivial estourar 50 req\u002Fs em um único IP. Quando isso acontece repetidamente, a Bybit retorna \u003Ccode>403\u003C\u002Fcode> e o IP entra numa janela de cooldown de aproximadamente 10 minutos.\u003C\u002Fp>\n\n\u003Cp>Estratégias de mitigação:\u003C\u002Fp>\n\n\u003Col>\n\u003Cli>Rate budgeting por endpoint: Use um token bucket ou semáforo para limitar a concorrência real.\u003C\u002Fli>\n\u003Cli>Backoff exponencial: Em \u003Ccode>403\u003C\u002Fcode> ou \u003Ccode>429\u003C\u002Fcode>, espere 1s, 2s, 4s, 8s e reinicie.\u003C\u002Fli>\n\u003Cli>Rotação de IP: Cada requisição sai de um IP diferente, efetivamente multiplicando seu teto de throughput.\u003C\u002Fli>\n\u003C\u002Fol>\n\n\u003Ch2>Geo-restrições da Bybit e como proxies residenciais restauram acesso\u003C\u002Fh2>\n\n\u003Cp>A Bybit restringe acesso de residentes em jurisdições como EUA, Reino Unido, Canadá, Singapura, Cuba, Irã, Coreia do Norte e outras. A filtragem acontece na borda da CloudFront: o IP de origem é comparado a uma lista de blocos de ASN\u002Fpaís e, se restrito, a CloudFront devolve 403 sem chegar ao backend da Bybit.\u003C\u002Fp>\n\n\u003Cp>Para bots de dados que rodam em clouds US\u002FEU, isso é fatal: mesmo endpoints públicos de mercado ficam inacessíveis. A solução é rotear o tráfego por um proxy residencial localizado em um país permitido, como Alemanha, Japão ou Brasil.\u003C\u002Fp>\n\n\u003Cp>Com o ProxyHat você controla o país diretamente no username:\u003C\u002Fp>\n\n\u003Cpre>\u003Ccode>http:\u002F\u002Fuser-country-DE:pass@gate.proxyhat.com:8080\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Cp>Para SOCKS5:\u003C\u002Fp>\n\n\u003Cpre>\u003Ccode>socks5:\u002F\u002Fuser-country-DE:pass@gate.proxyhat.com:1080\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Cp>Você também pode segmentar por cidade: \u003Ccode>user-country-DE-region-state_of_berlin-city-berlin\u003C\u002Fcode>. Consulte a lista completa em \u003Ca href=\"\u002Fpt\u002Flocations\">\u002Fpt\u002Flocations\u003C\u002Fa>.\u003C\u002Fp>\n\n\u003Ch2>Exemplo 1: curl com proxy bruto (linha de comando)\u003C\u002Fh2>\n\n\u003Cp>Antes de qualquer SDK, valide manualmente que o proxy funciona contra a Bybit:\u003C\u002Fp>\n\n\u003Cpre>\u003Ccode># Orderbook spot BTCUSDT via proxy residencial em DE\ncurl -x http:\u002F\u002Fuser-country-DE:SUA_SENHA@gate.proxyhat.com:8080 \\\n  &quot;https:\u002F\u002Fapi.bybit.com\u002Fv5\u002Fmarket\u002Forderbook?category=spot&amp;symbol=BTCUSDT&amp;limit=50&quot;\n\n# Tickers linear\nurl -x http:\u002F\u002Fuser-country-DE:SUA_SENHA@gate.proxyhat.com:8080 \\\n  &quot;https:\u002F\u002Fapi.bybit.com\u002Fv5\u002Fmarket\u002Ftickers?category=linear&quot;\n\n# Kline 1m, últimos 200 candles\nurl -x http:\u002F\u002Fuser-country-DE:SUA_SENHA@gate.proxyhat.com:8080 \\\n  &quot;https:\u002F\u002Fapi.bybit.com\u002Fv5\u002Fmarket\u002Fkline?category=linear&amp;symbol=ETHUSDT&amp;interval=1&amp;limit=200&quot;\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Cp>Se você receber JSON com \u003Ccode>retCode: 0\u003C\u002Fcode>, o proxy está funcionando. Se receber HTML da CloudFront com 403, troque o país (algumas saídas residenciais podem estar em ASNs bloqueados — rotacione).\u003C\u002Fp>\n\n\u003Ch2>Exemplo 2: Python com requests + proxy bruto\u003C\u002Fh2>\n\n\u003Cpre>\u003Ccode>import os\nimport time\nimport logging\nimport requests\nfrom requests.adapters import HTTPAdapter\nfrom urllib3.util.retry import Retry\n\nlogging.basicConfig(level=logging.INFO, format=&quot;%(asctime)s %(levelname)s %(message)s&quot;)\n\nBYBIT_BASE = &quot;https:\u002F\u002Fapi.bybit.com&quot;\nPROXY_USER = os.environ[&quot;PROXYHAT_USER&quot;]\nPROXY_PASS = os.environ[&quot;PROXYHAT_PASS&quot;]\nPROXY_URL = f&quot;http:\u002F\u002F{PROXY_USER}-country-DE:{PROXY_PASS}@gate.proxyhat.com:8080&quot;\n\nsession = requests.Session()\nretry = Retry(\n    total=5,\n    backoff_factor=1.5,  # 1.5s, 3s, 6s, 12s, 24s\n    status_forcelist=(429, 403, 500, 502, 503),\n    allowed_methods=[&quot;GET&quot;],\n)\nsession.mount(&quot;https:\u002F\u002F&quot;, HTTPAdapter(max_retries=retry))\nsession.proxies.update({&quot;http&quot;: PROXY_URL, &quot;https&quot;: PROXY_URL})\n\ndef fetch_orderbook(symbol: str, category: str = &quot;linear&quot;, limit: int = 50):\n    url = f&quot;{BYBIT_BASE}\u002Fv5\u002Fmarket\u002Forderbook&quot;\n    params = {&quot;category&quot;: category, &quot;symbol&quot;: symbol, &quot;limit&quot;: limit}\n    r = session.get(url, params=params, timeout=10)\n    r.raise_for_status()\n    body = r.json()\n    if body.get(&quot;retCode&quot;) != 0:\n        raise RuntimeError(f&quot;Bybit retCode={body.get(&apos;retCode&apos;)} msg={body.get(&apos;retMsg&apos;)}&quot;)\n    return body[&quot;result&quot;]\n\nif __name__ == &quot;__main__&quot;:\n    symbols = [&quot;BTCUSDT&quot;, &quot;ETHUSDT&quot;, &quot;SOLUSDT&quot;, &quot;XRPUSDT&quot;]\n    for sym in symbols:\n        try:\n            ob = fetch_orderbook(sym)\n            bid = float(ob[&quot;b&quot;][0][0])\n            ask = float(ob[&quot;a&quot;][0][0])\n            logging.info(&quot;%s bid=%s ask=%s spread=%.4f&quot;, sym, bid, ask, ask - bid)\n        except Exception as e:\n            logging.error(&quot;%s falhou: %s&quot;, sym, e)\n        time.sleep(0.2)  # rate budget: 5 req\u002Fs\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Cp>Note o rate budget de 0.2s entre chamadas — mesmo com proxy, respeitar o teto por IP evita desperdício de sessões. O \u003Ccode>Retry\u003C\u002Fcode> do urllib3 trata 403\u002F429 automaticamente com backoff exponencial.\u003C\u002Fp>\n\n\u003Ch2>Exemplo 3: Python com ProxyHat SDK (rotação automática)\u003C\u002Fh2>\n\n\u003Cp>O ProxyHat SDK abstrai a rotação de IP, retries e seleção de país. Você não precisa construir URLs de proxy manualmente:\u003C\u002Fp>\n\n\u003Cpre>\u003Ccode>import asyncio\nimport logging\nfrom proxyhat import ProxyHatClient  # pacote: pip install proxyhat\n\nlogging.basicConfig(level=logging.INFO, format=&quot;%(asctime)s %(levelname)s %(message)s&quot;)\n\nclient = ProxyHatClient(\n    username=&quot;SUA_SENHA_USER&quot;,\n    password=&quot;SUA_SENHA&quot;,\n    country=&quot;DE&quot;,\n    rotate=True,          # IP novo a cada requisição\n    max_retries=5,\n    backoff_factor=1.5,\n    timeout=10,\n)\n\nBYBIT = &quot;https:\u002F\u002Fapi.bybit.com\u002Fv5\u002Fmarket&quot;\n\nasync def fetch_tickers(category: str = &quot;linear&quot;):\n    async with client.get(f&quot;{BYBIT}\u002Ftickers&quot;, params={&quot;category&quot;: category}) as r:\n        data = await r.json()\n        if data[&quot;retCode&quot;] != 0:\n            raise RuntimeError(f&quot;retCode={data[&apos;retCode&apos;]} msg={data[&apos;retMsg&apos;]}&quot;)\n        return data[&quot;result&quot;][&quot;list&quot;]\n\nasync def fetch_orderbook(symbol: str, category: str = &quot;linear&quot;, limit: int = 50):\n    async with client.get(\n        f&quot;{BYBIT}\u002Forderbook&quot;,\n        params={&quot;category&quot;: category, &quot;symbol&quot;: symbol, &quot;limit&quot;: limit},\n    ) as r:\n        data = await r.json()\n        return data[&quot;result&quot;]\n\nasync def main():\n    tickers = await fetch_tickers(&quot;linear&quot;)\n    logging.info(&quot;Recebidos %d tickers linear&quot;, len(tickers))\n    symbols = [t[&quot;symbol&quot;] for t in tickers[:10]]\n    tasks = [fetch_orderbook(s) for s in symbols]\n    results = await asyncio.gather(*tasks, return_exceptions=True)\n    for sym, res in zip(symbols, results):\n        if isinstance(res, Exception):\n            logging.error(&quot;%s: %s&quot;, sym, res)\n        else:\n            logging.info(&quot;%s top bid=%s&quot;, sym, res[&quot;b&quot;][0][0])\n\nasyncio.run(main())\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Cp>Aqui usamos \u003Ccode>asyncio.gather\u003C\u002Fcode> para paralelizar 10 chamadas de orderbook. Como cada uma sai de um IP diferente via \u003Ccode>rotate=True\u003C\u002Fcode>, o teto de 50 req\u002Fs por IP não é um problema.\u003C\u002Fp>\n\n\u003Ch2>Exemplo 4: Node.js com axios e rotação de IP\u003C\u002Fh2>\n\n\u003Cpre>\u003Ccode>const axios = require(&apos;axios&apos;);\nconst { HttpsProxyAgent } = require(&apos;https-proxy-agent&apos;);\nconst { ProxyHat } = require(&apos;proxyhat&apos;);\n\nconst PROXYHAT_USER = process.env.PROXYHAT_USER;\nconst PROXYHAT_PASS = process.env.PROXYHAT_PASS;\n\n\u002F\u002F Cliente ProxyHat com rotação por requisição\nconst ph = new ProxyHat({\n  username: PROXYHAT_USER,\n  password: PROXYHAT_PASS,\n  country: &apos;DE&apos;,\n  rotate: true,\n  maxRetries: 5,\n  backoffFactor: 1.5,\n});\n\nconst BYBIT = &apos;https:\u002F\u002Fapi.bybit.com\u002Fv5\u002Fmarket&apos;;\n\nasync function fetchOrderbook(symbol, category = &apos;linear&apos;, limit = 50) {\n  const proxyUrl = await ph.nextProxyUrl(); \u002F\u002F http:\u002F\u002Fuser-country-DE:pass@gate.proxyhat.com:8080\n  const agent = new HttpsProxyAgent(proxyUrl);\n  const { data } = await axios.get(`${BYBIT}\u002Forderbook`, {\n    params: { category, symbol, limit },\n    httpsAgent: agent,\n    timeout: 10000,\n  });\n  if (data.retCode !== 0) {\n    throw new Error(`retCode=${data.retCode} msg=${data.retMsg}`);\n  }\n  return data.result;\n}\n\nasync function main() {\n  const symbols = [&apos;BTCUSDT&apos;, &apos;ETHUSDT&apos;, &apos;SOLUSDT&apos;, &apos;XRPUSDT&apos;, &apos;DOGEUSDT&apos;];\n  const results = await Promise.allSettled(\n    symbols.map((s) =&gt; fetchOrderbook(s).catch(async (err) =&gt; {\n      \u002F\u002F backoff manual em caso de 403\n      if (err.response &amp;&amp; err.response.status === 403) {\n        await new Promise((r) =&gt; setTimeout(r, 2000));\n        return fetchOrderbook(s);\n      }\n      throw err;\n    }))\n  );\n  results.forEach((r, i) =&gt; {\n    if (r.status === &apos;fulfilled&apos;) {\n      console.log(symbols[i], &apos;bid=&apos;, r.value.b[0][0], &apos;ask=&apos;, r.value.a[0][0]);\n    } else {\n      console.error(symbols[i], &apos;falhou:&apos;, r.reason.message);\n    }\n  });\n}\n\nmain();\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Cp>O \u003Ccode>Promise.allSettled\u003C\u002Fcode> garante que uma falha em um símbolo não derruba o batch inteiro. O backoff manual em 403 complementa o retry interno do SDK.\u003C\u002Fp>\n\n\u003Ch2>Exemplo 5: Sessões sticky para paginação de klines\u003C\u002Fh2>\n\n\u003Cp>O endpoint \u003Ccode>\u002Fv5\u002Fmarket\u002Fkline\u003C\u002Fcode> retorna no máximo 1000 candles por chamada. Para construir séries históricas longas, você pagina via \u003Ccode>start\u003C\u002Fcode> e \u003Ccode>end\u003C\u002Fcode> (timestamps em ms). O problema: se cada chamada sair de um IP diferente, você pode acabar com lacunas se um IP for banido no meio da sequência.\u003C\u002Fp>\n\n\u003Cp>A solução é uma sessão sticky — o ProxyHat mantém o mesmo IP de saída durante toda a sessão:\u003C\u002Fp>\n\n\u003Cpre>\u003Ccode>import os\nimport time\nimport requests\n\nPROXY_USER = os.environ[&quot;PROXYHAT_USER&quot;]\nPROXY_PASS = os.environ[&quot;PROXYHAT_PASS&quot;]\n\n# Sessão sticky: mesmo IP durante toda a coleta de klines\nPROXY_URL = f&quot;http:\u002F\u002F{PROXY_USER}-sid-kline-btc-001:{PROXY_PASS}@gate.proxyhat.com:8080&quot;\n\nsession = requests.Session()\nsession.proxies.update({&quot;http&quot;: PROXY_URL, &quot;https&quot;: PROXY_URL})\n\ndef fetch_klines(symbol, category, interval, start_ms, end_ms):\n    url = &quot;https:\u002F\u002Fapi.bybit.com\u002Fv5\u002Fmarket\u002Fkline&quot;\n    params = {\n        &quot;category&quot;: category,\n        &quot;symbol&quot;: symbol,\n        &quot;interval&quot;: interval,\n        &quot;start&quot;: start_ms,\n        &quot;end&quot;: end_ms,\n        &quot;limit&quot;: 1000,\n    }\n    r = session.get(url, params=params, timeout=10)\n    r.raise_for_status()\n    body = r.json()\n    if body[&quot;retCode&quot;] != 0:\n        raise RuntimeError(f&quot;retCode={body[&apos;retCode&apos;]} msg={body[&apos;retMsg&apos;]}&quot;)\n    return body[&quot;result&quot;][&quot;list&quot;]\n\ndef collect_history(symbol, category, interval, days=30):\n    end_ms = int(time.time() * 1000)\n    start_ms = end_ms - days * 24 * 3600 * 1000\n    all_candles = []\n    cursor = start_ms\n    while cursor &lt; end_ms:\n        batch = fetch_klines(symbol, category, interval, cursor, end_ms)\n        if not batch:\n            break\n        all_candles.extend(batch)\n        # próximo batch: último timestamp + 1ms\n        cursor = int(batch[-1][0]) + 1\n        time.sleep(0.15)  # rate budget: ~6 req\u002Fs, abaixo do teto de 10\n    return all_candles\n\nif __name__ == &quot;__main__&quot;:\n    candles = collect_history(&quot;BTCUSDT&quot;, &quot;linear&quot;, &quot;60&quot;, days=7)\n    print(f&quot;Coletados {len(candles)} candles de 1h em 7 dias&quot;)\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Cp>O flag \u003Ccode>-sid-kline-btc-001\u003C\u002Fcode> no username garante que o ProxyHat atribua um IP residencial fixo para essa string de sessão. Se você rodar múltiplos símbolos em paralelo, use IDs de sessão distintos por símbolo (\u003Ccode>-sid-kline-eth-001\u003C\u002Fcode>, etc.) para distribuir a carga entre IPs.\u003C\u002Fp>\n\n\u003Ch2>Exemplo 6: WebSocket público vs REST snapshot\u003C\u002Fh2>\n\n\u003Cp>Para orderbook em tempo real, REST polling é ineficiente. A Bybit oferece um stream WebSocket público em \u003Ccode>wss:\u002F\u002Fstream.bybit.com\u002Fv5\u002Fpublic\u002Flinear\u003C\u002Fcode> com o canal \u003Ccode>orderbook.50.BTCUSDT\u003C\u002Fcode>, que entrega snapshots incrementais a ~10ms. Para bots de market-making, essa é a fonte canônica.\u003C\u002Fp>\n\n\u003Cpre>\u003Ccode>import json\nimport asyncio\nimport websockets\n\nasync def listen_orderbook():\n    url = &quot;wss:\u002F\u002Fstream.bybit.com\u002Fv5\u002Fpublic\u002Flinear&quot;\n    async with websockets.connect(url, ping_interval=20) as ws:\n        # Snapshot inicial\n        await ws.send(json.dumps({\n            &quot;op&quot;: &quot;subscribe&quot;,\n            &quot;args&quot;: [&quot;orderbook.50.BTCUSDT&quot;]\n        }))\n        async for msg in ws:\n            data = json.loads(msg)\n            if data.get(&quot;topic&quot;, &quot;&quot;).startswith(&quot;orderbook.50&quot;):\n                ob = data[&quot;data&quot;]\n                top_bid = ob[&quot;b&quot;][0][0] if ob[&quot;b&quot;] else None\n                top_ask = ob[&quot;a&quot;][0][0] if ob[&quot;a&quot;] else None\n                print(f&quot;type={data[&apos;type&apos;]} bid={top_bid} ask={top_ask}&quot;)\n\nasyncio.run(listen_orderbook())\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Cp>Comparação rápida:\u003C\u002Fp>\n\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\u003Cth>Aspecto\u003C\u002Fth>\u003Cth>REST \u002Fv5\u002Fmarket\u002Forderbook\u003C\u002Fth>\u003Cth>WebSocket orderbook.50\u003C\u002Fth>\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\n\u003Ctr>\u003Ctd>Latência\u003C\u002Ftd>\u003Ctd>~50-200ms (com proxy)\u003C\u002Ftd>\u003Ctd>~10-50ms\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Taxa de atualização\u003C\u002Ftd>\u003Ctd>Sob demanda (polling)\u003C\u002Ftd>\u003Ctd>Push em tempo real\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Custo de IP\u003C\u002Ftd>\u003Ctd>Alto (rate limit por IP)\u003C\u002Ftd>\u003Ctd>Baixo (1 conexão persistente)\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Ideal para\u003C\u002Ftd>\u003Ctd>Snapshot histórico, backfill\u003C\u002Ftd>\u003Ctd>Market-making, execução ao vivo\u003C\u002Ftd>\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\n\n\u003Cp>Nota: o WebSocket público da Bybit também pode sofrer geo-restrição. Se necessário, conecte via \u003Ccode>socks5:\u002F\u002Fuser-country-DE:pass@gate.proxyhat.com:1080\u003C\u002Fcode>.\u003C\u002Fp>\n\n\u003Ch2>Erros comuns e edge cases\u003C\u002Fh2>\n\n\u003Cul>\n\u003Cli>403 sem corpo JSON: É CloudFront bloqueando por geo. Troque o país do proxy.\u003C\u002Fli>\n\u003Cli>retCode 10001: Parâmetro inválido — verifique \u003Ccode>category\u003C\u002Fcode> (spot vs linear vs option).\u003C\u002Fli>\n\u003Cli>retCode 403 ou 429: Rate limit excedido. Faça backoff e reduza a concorrência.\u003C\u002Fli>\n\u003Cli>IP banido por 10 minutos: Se você insiste após 403, o ban se prolonga. Implemente circuit breaker.\u003C\u002Fli>\n\u003Cli>Lacunas em klines: Use sessões sticky e valide \u003Ccode>retCode\u003C\u002Fcode> em cada batch.\u003C\u002Fli>\n\u003Cli>Símbolos deslistados: Sempre consulte \u003Ccode>\u002Fv5\u002Fmarket\u002Finstruments-info\u003C\u002Fcode> antes de raspar tickers de símbolos que podem ter sido removidos.\u003C\u002Fli>\n\u003C\u002Ful>\n\n\u003Ch2>Setup no ProxyHat e links úteis\u003C\u002Fh2>\n\n\u003Col>\n\u003Cli>Crie sua conta em \u003Ca href=\"\u002Fpt\u002Fpricing\">\u002Fpt\u002Fpricing\u003C\u002Fa> e escolha um plano residencial adequado ao seu volume.\u003C\u002Fli>\n\u003Cli>Configure as variáveis de ambiente \u003Ccode>PROXYHAT_USER\u003C\u002Fcode> e \u003Ccode>PROXYHAT_PASS\u003C\u002Fcode>.\u003C\u002Fli>\n\u003Cli>Escolha países permitidos pela Bybit (DE, JP, BR, etc.) consultando \u003Ca href=\"\u002Fpt\u002Flocations\">\u002Fpt\u002Flocations\u003C\u002Fa>.\u003C\u002Fli>\n\u003Cli>Para casos de uso de scraping em geral, veja \u003Ca href=\"\u002Fpt\u002Fuse-cases\u002Fweb-scraping\">\u002Fpt\u002Fuse-cases\u002Fweb-scraping\u003C\u002Fa>.\u003C\u002Fli>\n\u003Cli>Para tracking de SERP e monitoramento de concorrentes, veja \u003Ca href=\"\u002Fpt\u002Fuse-cases\u002Fserp-tracking\">\u002Fpt\u002Fuse-cases\u002Fserp-tracking\u003C\u002Fa>.\u003C\u002Fli>\n\u003Cli>Documentação técnica do ProxyHat: \u003Ca href=\"https:\u002F\u002Fdocs.proxyhat.com\u002F\" rel=\"noopener noreferrer\">docs.proxyhat.com\u003C\u002Fa>.\u003C\u002Fli>\n\u003C\u002Fol>\n\n\u003Ch2>Key Takeaways\u003C\u002Fh2>\n\n\u003Cul>\n\u003Cli>Rate limit por IP é o gargalo número 1. O orderbook tem ~50 req\u002Fs por IP; bursts derrubam o IP por ~10 min.\u003C\u002Fli>\n\u003Cli>Geo-restrição vem da CloudFront. 403 sem JSON = bloqueio de país. Use proxy residencial em país permitido.\u003C\u002Fli>\n\u003Cli>Sessões sticky para paginação. Use \u003Ccode>-sid-xxx\u003C\u002Fcode> no username para manter o mesmo IP em sequências longas de klines.\u003C\u002Fli>\n\u003Cli>WebSocket para tempo real, REST para snapshots. Não faça polling de orderbook se você precisa de &lt;50ms de latência.\u003C\u002Fli>\n\u003Cli>Sempre valide retCode. A Bybit não usa HTTP status para erros de aplicação — \u003Ccode>retCode != 0\u003C\u002Fcode> exige tratamento.\u003C\u002Fli>\n\u003C\u002Ful>","Dados de mercado cripto com proxies rotativos (Bybit V5) | ProxyHat","Guia para desenvolvedores sobre como raspar a Bybit V5 Market API com proxies rotativos via ProxyHat: rate limits, geo-restrições, klines e WebSocket.","\u002Fpt\u002Fblog\u002Fcomo-raspar-bybit-v5-market-api-proxies",null,"Dados de mercado cripto com proxies rotativos | ProxyHat","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fpt\u002Fcomo-raspar-bybit-v5-market-api-proxies-og.webp",[18,21,24,27],{"question":19,"answer":20},"Por que isso importa para usuários de proxy?","Porque a Bybit impõe limites estritos por IP (~50 req\u002Fs no orderbook) e bloqueia regiões inteiras via CloudFront. Sem rotação de IP, um bot de trading que monitora 50 símbolos em polling pode ser banido em minutos. Proxies residenciais rotativos multiplicam o teto efetivo de throughput e restauram o acesso de clouds em países restritos.",{"question":22,"answer":23},"Qual tipo de proxy funciona melhor para raspar a Bybit V5 Market API?","Proxies residenciais são a melhor escolha porque seus IPs vêm de ASNs de ISPs reais, dificilmente bloqueados pela CloudFront. Datacenter proxies tendem a ser flaggeados como datacenter e bloqueados mais rápido. Para paginação de klines, use sessões sticky (-sid-xxx) para manter consistência de IP durante a sequência.",{"question":25,"answer":26},"Como evitar bloqueios ao raspar a Bybit V5 Market API?","Implemente rate budgeting (token bucket por endpoint), backoff exponencial em 403\u002F429, circuit breaker após N falhas consecutivas, e rotação de IP via ProxyHat. Mantenha concorrência abaixo do teto por IP (ex.: 5 req\u002Fs para orderbook com 1 IP, ou 50 req\u002Fs com 10 IPs rotativos). Sempre valide \u003Ccode>retCode\u003C\u002Fcode> no envelope de resposta e consulte a documentação oficial para limites atualizados.",{"question":28,"answer":29},"WebSocket público da Bybit também precisa de proxy?","Pode precisar. O endpoint WebSocket wss:\u002F\u002Fstream.bybit.com\u002Fv5\u002Fpublic\u002Flinear também passa pela CloudFront e pode sofrer geo-restrição. Se sua infraestrutura está em país bloqueado, conecte via SOCKS5 (socks5:\u002F\u002Fuser-country-DE:pass@gate.proxyhat.com:1080). WebSocket tem vantagem sobre REST: uma única conexão persistente substitui centenas de polls.",false,"2026-08-03T16:09:16+00:00","2026-10-04T02:43:17+00:00","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fpt\u002Fcomo-raspar-bybit-v5-market-api-proxies-master.webp","How to Scrape the Bybit V5 Market API with Rotating Proxies","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fpt\u002Fcomo-raspar-bybit-v5-market-api-proxies-card.webp",12,{"name":38,"slug":39,"bio":40,"avatar_url":14,"website_url":14,"social_links":14},"ProxyHat Team","proxyhat-team","The ProxyHat editorial team covers proxies, web scraping, and data extraction.",[42],{"id":43,"slug":44,"name":45,"description":14,"meta_title":46,"meta_description":47,"parent_id":14},4,"guias-desenvolvedores","Guias para Desenvolvedores","Guias para Desenvolvedores | Blog ProxyHat","Tutoriais de código e guias SDK para integrar proxies em suas aplicações.",[],{"de":50,"fr":51,"it":52,"ko":53,"pt":13,"zh":54,"ru":55,"pl":56,"es":57,"en":58,"ja":59,"x-default":58},"\u002Fde\u002Fblog\u002Fbybit-v5-market-api-mit-rotating-proxies-scrapen","\u002Ffr\u002Fblog\u002Fscraper-api-bybit-v5-proxys-rotatifs","\u002Fit\u002Fblog\u002Fscrape-bybit-v5-market-api-proxy","\u002Fko\u002Fblog\u002Fbybit-v5-market-api-proxy-scraping","\u002Fcn\u002Fblog\u002Fscrape-bybit-v5-market-api-proxy","\u002Fru\u002Fblog\u002Fkak-skrejpit-bybit-v5-market-api","\u002Fpl\u002Fblog\u002Fjak-scrapowac-bybit-v5-api-proxy","\u002Fes\u002Fblog\u002Fscrapear-api-mercado-bybit-v5-proxies","\u002Fblog\u002Fscrape-bybit-v5-market-api-rotating-proxies","\u002Fja\u002Fblog\u002Fbybit-v5-market-api-proxy-scraping",{"de":50,"fr":51,"it":52,"ko":53,"pt":13,"zh":54,"ru":55,"pl":56,"es":57,"en":58,"ja":59,"tr":61},"\u002Ftr\u002Fblog\u002Fbybit-v5-market-api-dondurulen-proxy",87,[64,80,96,111],{"id":65,"slug":66,"title":67,"excerpt":68,"featured_image_url":69,"featured_image_alt":70,"card_image_url":71,"og_image_url":72,"published_at":73,"updated_at":73,"content_updated_at":74,"reading_time_minutes":36,"is_featured":30,"indexable":30,"views":75,"author":76,"categories":77,"tags":79},176,"guia-got-scraping-nodejs-proxies-residenciais","Guia de got-scraping em Node.js com proxies residenciais","Aprenda a usar got-scraping em Node.js com proxies residenciais: geração de headers coerentes, HTTP\u002F2, rotação de IPs e padrões de produção para scraping em escala.","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fpt\u002Fguia-got-scraping-nodejs-proxies-residenciais-master.webp","got-scraping in Node.js: A Developer's Guide with Residential Proxies","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fpt\u002Fguia-got-scraping-nodejs-proxies-residenciais-card.webp","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fpt\u002Fguia-got-scraping-nodejs-proxies-residenciais-og.webp","2026-08-04T16:05:06+00:00","2026-10-03T08:57:48+00:00",121,{"name":38,"slug":39,"bio":40,"avatar_url":14,"website_url":14,"social_links":14},[78],{"id":43,"slug":44,"name":45,"description":14,"meta_title":46,"meta_description":47,"parent_id":14},[],{"id":81,"slug":82,"title":83,"excerpt":84,"featured_image_url":85,"featured_image_alt":86,"card_image_url":87,"og_image_url":88,"published_at":89,"updated_at":89,"content_updated_at":90,"reading_time_minutes":36,"is_featured":30,"indexable":30,"views":91,"author":92,"categories":93,"tags":95},175,"proxies-rotativos-em-colly","Proxies Rotativos em Colly: Guia para Desenvolvedores Go","Aprenda a integrar proxies rotativos residenciais no framework Colly de Go, usando RoundRobinProxySwitcher, SetProxyFunc, sessões sticky e geo-targeting para scraping de alta escala.","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fpt\u002Fproxies-rotativos-em-colly-master.webp","Rotating Proxies in Colly: A Framework-Idiomatic Guide for Go Developers","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fpt\u002Fproxies-rotativos-em-colly-card.webp","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fpt\u002Fproxies-rotativos-em-colly-og.webp","2026-08-04T10:05:34+00:00","2026-10-03T23:53:00+00:00",71,{"name":38,"slug":39,"bio":40,"avatar_url":14,"website_url":14,"social_links":14},[94],{"id":43,"slug":44,"name":45,"description":14,"meta_title":46,"meta_description":47,"parent_id":14},[],{"id":97,"slug":98,"title":99,"excerpt":100,"featured_image_url":101,"featured_image_alt":102,"card_image_url":103,"og_image_url":104,"published_at":105,"updated_at":105,"content_updated_at":32,"reading_time_minutes":36,"is_featured":30,"indexable":4,"views":106,"author":107,"categories":108,"tags":110},194,"como-raspar-api-binance-proxies","Limites de peso em APIs de exchanges cripto: como coletar dados de mercado com proxies (exemplo Binance)","Guia prático para coletar dados públicos de mercado da Binance REST API em escala usando proxies residenciais rotativos, com exemplos em Python e Node.js, controle de peso e mitigação de banimentos por IP.","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fpt\u002Fcomo-raspar-api-binance-proxies-master.webp","How to Scrape the Binance REST API with Proxies: A Developer Guide","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fpt\u002Fcomo-raspar-api-binance-proxies-card.webp","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fpt\u002Fcomo-raspar-api-binance-proxies-og.webp","2026-08-03T10:04:04+00:00",82,{"name":38,"slug":39,"bio":40,"avatar_url":14,"website_url":14,"social_links":14},[109],{"id":43,"slug":44,"name":45,"description":14,"meta_title":46,"meta_description":47,"parent_id":14},[],{"id":112,"slug":113,"title":114,"excerpt":115,"featured_image_url":116,"featured_image_alt":117,"card_image_url":118,"og_image_url":119,"published_at":120,"updated_at":120,"content_updated_at":121,"reading_time_minutes":36,"is_featured":30,"indexable":30,"views":122,"author":123,"categories":124,"tags":126},172,"usar-proxies-swift-urlsession","Usar Proxies em Swift com URLSession: Guia Completo para iOS e macOS","Aprenda a configurar proxies residenciais em Swift usando URLSession: HTTP, SOCKS5, autenticação, geo-targeting, async\u002Fawait e dicas de produção para iOS e macOS.","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fpt\u002Fusar-proxies-swift-urlsession-master.webp","Using Proxies in Swift: A Code-First Guide to URLSession, SOCKS5 & Residential IPs","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fpt\u002Fusar-proxies-swift-urlsession-card.webp","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fpt\u002Fusar-proxies-swift-urlsession-og.webp","2026-07-26T16:03:44+00:00","2026-10-03T08:57:47+00:00",230,{"name":38,"slug":39,"bio":40,"avatar_url":14,"website_url":14,"social_links":14},[125],{"id":43,"slug":44,"name":45,"description":14,"meta_title":46,"meta_description":47,"parent_id":14},[],[]]