[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"blog-post-ja-bybit-v5-market-api-proxy-scraping":3},{"success":4,"payload":5,"related":60,"errors":124},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":27,"allow_follow":4,"published_at":28,"updated_at":28,"content_updated_at":29,"featured_image_url":30,"featured_image_alt":31,"card_image_url":32,"reading_time_minutes":33,"author":34,"categories":38,"tags":45,"alternates":46,"locale_paths":57,"views":59},195,"bybit-v5-market-api-proxy-scraping","暗号資産取引所の市場データをローテーションプロキシで収集する完全ガイド（Bybit V5 APIの例）","Bybit V5 Market APIのorderbook・tickers・klineエンドポイントをローテーションプロキシ経由でスクレイピングする方法を、Node.js・Pythonのコード例とともに解説。レート制限・地域制限の回避策もカバーします。","\u003Cp>\u003Cstrong>免責事項:\u003C\u002Fstrong> 本記事はBybitの公開市場データエンドポイントへのアクセスに関する技術的解説です。Bybitの\u003Ca href=\"https:\u002F\u002Fwww.bybit.com\u002Fen-US\u002Fterms\" rel=\"noopener noreferrer\">利用規約\u003C\u002Fa>および該当管轄区の法律を遵守してください。スクレイピングを行う前に必ず公式ドキュメントとToSを確認し、許可された範囲でデータを収集してください。\u003C\u002Fp>\n\n\u003Cp>Bybit V5 Market APIのローテーションプロキシによるスクレイピングは、仮想通貨取引ボットや市場データパイプラインを構築する開発者にとって中核的な課題です。BybitはV5統合APIでエンドポイント構造を刷新しましたが、IPベースのレート制限と地理的制限により、高頻度データ収集は容易ではありません。本ガイドでは、\u003Ccode>api.bybit.com\u002Fv5\u002Fmarket\u002Forderbook\u003C\u002Fcode>、\u003Ccode>\u002Fv5\u002Fmarket\u002Ftickers\u003C\u002Fcode>、\u003Ccode>\u002Fv5\u002Fmarket\u002Fkline\u003C\u002Fcode>、\u003Ccode>\u002Fv5\u002Fmarket\u002Frecent-trade\u003C\u002Fcode>の各エンドポイントを、ProxyHatのローテーションプロキシ（\u003Ccode>gate.proxyhat.com:8080\u003C\u002Fcode>）経由でスクレイピングする実践的な方法を、Node.js・Pythonのコード例とともに解説します。\u003C\u002Fp>\n\n\u003Ch2>Bybit V5 Market APIのエンドポイント構造とレスポンスエンベロープ\u003C\u002Fh2>\n\n\u003Cp>Bybit V5 Market APIは、取引所の公開市場データへのアクセスを提供するRESTエンドポイント群です。認証不要でアクセスでき、公式V5ドキュメントに仕様が公開されています。主要なエンドポイントは以下の通りです。\u003C\u002Fp>\n\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\u003Cth>エンドポイント\u003C\u002Fth>\u003Cth>メソッド\u003C\u002Fth>\u003Cth>必須パラメータ\u003C\u002Fth>\u003Cth>用途\u003C\u002Fth>\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\n\u003Ctr>\u003Ctd>\u003Ccode>\u002Fv5\u002Fmarket\u002Forderbook\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>GET\u003C\u002Ftd>\u003Ctd>category, symbol\u003C\u002Ftd>\u003Ctd>板情報（オーダーブック）のスナップショット取得\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>\u003Ccode>\u002Fv5\u002Fmarket\u002Ftickers\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>GET\u003C\u002Ftd>\u003Ctd>category\u003C\u002Ftd>\u003Ctd>全銘柄または指定銘柄のティッカー情報（価格、出来高等）\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>\u003Ccode>\u002Fv5\u002Fmarket\u002Fkline\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>GET\u003C\u002Ftd>\u003Ctd>category, symbol, interval\u003C\u002Ftd>\u003Ctd>ローソク足（OHLCV）データの取得\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>\u003Ccode>\u002Fv5\u002Fmarket\u002Frecent-trade\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>GET\u003C\u002Ftd>\u003Ctd>category, symbol\u003C\u002Ftd>\u003Ctd>直近の約定履歴取得\u003C\u002Ftd>\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\n\n\u003Ch3>categoryパラメータの理解\u003C\u002Fh3>\n\n\u003Cp>V5 APIの重要な設計は \u003Ccode>category\u003C\u002Fcode> パラメータです。これは \u003Ccode>spot\u003C\u002Fcode>、\u003Ccode>linear\u003C\u002Fcode>、\u003Ccode>inverse\u003C\u002Fcode>、\u003Ccode>option\u003C\u002Fcode> のいずれかを指定し、取得する市場のタイプを切り替えます。例えば、\u003Ccode>\u002Fv5\u002Fmarket\u002Forderbook?category=spot&symbol=BTCUSDT\u003C\u002Fcode> は現物のBTCUSDT板情報を返し、\u003Ccode>category=linear\u003C\u002Fcode> はUSDT無期限先物の板情報を返します。各エンドポイントでサポートされるcategoryは異なるため、ドキュメントで確認が必要です。\u003C\u002Fp>\n\n\u003Ch3>retCode \u002F retMsg レスポンスエンベロープ\u003C\u002Fh3>\n\n\u003Cp>Bybit V5のすべてのレスポンスは統一されたJSONエンベロープで返されます。\u003C\u002Fp>\n\n\u003Cpre>\u003Ccode>{\n  &quot;retCode&quot;: 0,\n  &quot;retMsg&quot;: &quot;OK&quot;,\n  &quot;result&quot;: {\n    &quot;category&quot;: &quot;spot&quot;,\n    &quot;symbol&quot;: &quot;BTCUSDT&quot;,\n    &quot;bids&quot;: [[&quot;42000.50&quot;, &quot;1.234&quot;], ...],\n    &quot;asks&quot;: [[&quot;42000.60&quot;, &quot;0.567&quot;], ...]\n  },\n  &quot;retExtInfo&quot;: {},\n  &quot;time&quot;: 1700000000000\n}\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Cp>\u003Ccode>retCode\u003C\u002Fcode> が \u003Ccode>0\u003C\u002Fcode> の場合は成功、それ以外はエラーです。\u003Ccode>retMsg\u003C\u002Fcode> には人間可読なメッセージが含まれます。スクレイピング時は必ず \u003Ccode>retCode\u003C\u002Fcode> をチェックし、非ゼロの場合はリトライまたはエラーハンドリングを行う必要があります。HTTPステータスが200でも \u003Ccode>retCode\u003C\u002Fcode> が非ゼロのケースがある点に注意してください。\u003C\u002Fp>\n\n\u003Ch2>BybitのIPベースレート制限と403バンの仕組み\u003C\u002Fh2>\n\n\u003Cp>BybitはエンドポイントごとにIPベースのレート制限を設けています。\u003Ccode>\u002Fv5\u002Fmarket\u002Forderbook\u003C\u002Fcode> は高頻度アクセスが想定されるため比較的緩い制限ですが、バースト的なアクセスは制限に到達しやすくなります。制限を超過すると以下が発生します。\u003C\u002Fp>\n\n\u003Cul>\n\u003Cli>\u003Cstrong>HTTP 403レスポンス:\u003C\u002Fstrong> レート制限超過時に即座に返されます。\u003C\u002Fli>\n\u003Cli>\u003Cstrong>IPバンウィンドウ:\u003C\u002Fstrong> 制限超過後、約10分間そのIPからのアクセスがブロックされます。\u003C\u002Fli>\n\u003Cli>\u003Cstrong>エンドポイント別カウント:\u003C\u002Fstrong> \u003Ccode>orderbook\u003C\u002Fcode> へのバーストは \u003Ccode>tickers\u003C\u002Fcode> の制限には影響しませんが、同一IPでの全体的なリクエスト頻度は監視されます。\u003C\u002Fli>\n\u003C\u002Ful>\n\n\u003Cp>この仕組みがローテーションプロキシを必要とする理由です。単一IPで高頻度に \u003Ccode>api.bybit.com\u002Fv5\u002Fmarket\u002Forderbook\u003C\u002Fcode> を叩くと、数分以内に403とIPバンが発生し、データ収集パイプラインが停止します。リクエストごとにIPをローテーションすることで、各IPのレート制限クォータを独立して消費できます。\u003C\u002Fp>\n\n\u003Ch2>Bybitの地理的制限と住宅プロキシによる回避\u003C\u002Fh2>\n\n\u003Cp>Bybitは規制上の理由から、米国、英国、および一部制限地域からのアクセスをブロックしています。このブロックは\u003Ca href=\"https:\u002F\u002Faws.amazon.com\u002Fcloudfront\u002F\" rel=\"noopener noreferrer\">AWS CloudFront\u003C\u002Fa>のジオフィルタリングレイヤーで実装されており、IPの地理的位置に基づいてHTTP 403を返します。データセンタープロキシを使用すると、そのIPが制限地域のデータセンターに属している場合、CloudFrontレベルでブロックされる可能性があります。\u003C\u002Fp>\n\n\u003Cp>ProxyHatの\u003Ca href=\"\u002Fja\u002Fproxy\u002Fresidential\">住宅プロキシ\u003C\u002Fa>を使用することで、許可された国からの実際のISP IPアドレスでアクセスできます。ユーザー名にジオターゲティングフラグを指定するだけで、アクセス元の国を制御できます。\u003C\u002Fp>\n\n\u003Cpre>\u003Ccode># 日本からのアクセス\nhttp:\u002F\u002Fuser-country-JP:pass@gate.proxyhat.com:8080\n\n# ドイツからのアクセス\nhttp:\u002F\u002Fuser-country-DE:pass@gate.proxyhat.com:8080\n\n# シンガポールからのアクセス（Bybit本社所在地）\nhttp:\u002F\u002Fuser-country-SG:pass@gate.proxyhat.com:8080\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Cp>ProxyHatの利用可能なロケーションは\u003Ca href=\"\u002Fja\u002Flocations\">ロケーション一覧\u003C\u002Fa>で確認できます。価格については\u003Ca href=\"\u002Fja\u002Fpricing\">プランページ\u003C\u002Fa>を参照してください。\u003C\u002Fp>\n\n\u003Ch2>実装例1: curlでの基本アクセス（プロキシなし vs プロキシあり）\u003C\u002Fh2>\n\n\u003Cp>まずはcurlでの基本比較から始めます。\u003C\u002Fp>\n\n\u003Cpre>\u003Ccode># プロキシなし（制限地域からの場合、403の可能性）\ncurl -s &quot;https:\u002F\u002Fapi.bybit.com\u002Fv5\u002Fmarket\u002Forderbook?category=spot&amp;symbol=BTCUSDT&amp;limit=50&quot;\n\n# ProxyHatローテーションプロキシ経由（日本IP）\ncurl -s -x &quot;http:\u002F\u002Fuser-country-JP:pass@gate.proxyhat.com:8080&quot; \\\n  &quot;https:\u002F\u002Fapi.bybit.com\u002Fv5\u002Fmarket\u002Forderbook?category=spot&amp;symbol=BTCUSDT&amp;limit=50&quot;\n\n# SOCKS5経由\ncurl -s -x &quot;socks5:\u002F\u002Fuser-country-JP:pass@gate.proxyhat.com:1080&quot; \\\n  &quot;https:\u002F\u002Fapi.bybit.com\u002Fv5\u002Fmarket\u002Ftickers?category=linear&quot;\n\n# kline取得（1分足、200件）\ncurl -s -x &quot;http:\u002F\u002Fuser-country-JP:pass@gate.proxyhat.com:8080&quot; \\\n  &quot;https:\u002F\u002Fapi.bybit.com\u002Fv5\u002Fmarket\u002Fkline?category=spot&amp;symbol=ETHUSDT&amp;interval=1&amp;limit=200&quot;\n\n# 直近の約定履歴\ncurl -s -x &quot;http:\u002F\u002Fuser-country-JP:pass@gate.proxyhat.com:8080&quot; \\\n  &quot;https:\u002F\u002Fapi.bybit.com\u002Fv5\u002Fmarket\u002Frecent-trade?category=spot&amp;symbol=BTCUSDT&amp;limit=50&quot;\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Ch2>実装例2: Node.js (axios) で複数銘柄のIPローテーション\u003C\u002Fh2>\n\n\u003Cp>次に、Node.jsで複数銘柄のオーダーブックをローテーションプロキシ経由で取得する例を示します。ProxyHat SDKパターンと生プロキシパターンを並べて示します。\u003C\u002Fp>\n\n\u003Cpre>\u003Ccode>\u002F\u002F ===== 生プロキシパターン (axios + http-proxy-agent) =====\nconst axios = require(&apos;axios&apos;);\nconst { HttpsProxyAgent } = require(&apos;https-proxy-agent&apos;);\n\nconst PROXYHAT_HOST = &apos;gate.proxyhat.com&apos;;\nconst PROXYHAT_PORT = 8080;\nconst PROXY_USER = &apos;user-country-JP&apos;;\nconst PROXY_PASS = &apos;pass&apos;;\n\nconst proxyUrl = `http:\u002F\u002F${PROXY_USER}:${PROXY_PASS}@${PROXYHAT_HOST}:${PROXYHAT_PORT}`;\nconst agent = new HttpsProxyAgent(proxyUrl);\n\nconst symbols = [&apos;BTCUSDT&apos;, &apos;ETHUSDT&apos;, &apos;SOLUSDT&apos;, &apos;XRPUSDT&apos;, &apos;DOGEUSDT&apos;];\n\nasync function fetchOrderbook(symbol, retries = 3) {\n  const url = `https:\u002F\u002Fapi.bybit.com\u002Fv5\u002Fmarket\u002Forderbook?category=spot&amp;symbol=${symbol}&amp;limit=50`;\n  for (let attempt = 0; attempt &lt; retries; attempt++) {\n    try {\n      const res = await axios.get(url, {\n        httpsAgent: agent,\n        timeout: 10000,\n        headers: {\n          &apos;Accept&apos;: &apos;application\u002Fjson&apos;,\n          &apos;User-Agent&apos;: &apos;Mozilla\u002F5.0 (compatible; MarketDataBot\u002F1.0)&apos;\n        }\n      });\n      if (res.data.retCode === 0) {\n        return res.data.result;\n      } else {\n        throw new Error(`retCode=${res.data.retCode}, retMsg=${res.data.retMsg}`);\n      }\n    } catch (err) {\n      const wait = Math.pow(2, attempt) * 500;\n      console.error(`[${symbol}] attempt ${attempt + 1} failed: ${err.message}, retry in ${wait}ms`);\n      if (attempt === retries - 1) throw err;\n      await new Promise(r =&gt; setTimeout(r, wait));\n    }\n  }\n}\n\n\u002F\u002F 全銘柄を並列取得（ただしレート制限を考慮して5並列まで）\nasync function main() {\n  const results = await Promise.allSettled(\n    symbols.map(sym =&gt; fetchOrderbook(sym))\n  );\n  results.forEach((r, i) =&gt; {\n    if (r.status === &apos;fulfilled&apos;) {\n      const bids = r.value.bids.slice(0, 3);\n      console.log(`${symbols[i]}: best bid=${bids[0]?.[0]}, asks count=${r.value.asks.length}`);\n    } else {\n      console.error(`${symbols[i]}: FAILED - ${r.reason.message}`);\n    }\n  });\n}\n\nmain();\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Cpre>\u003Ccode>\u002F\u002F ===== ProxyHat SDKパターン =====\n\u002F\u002F ProxyHat SDK はローテーション・リトライ・ジオターゲティングを抽象化\nconst { ProxyHatClient } = require(&apos;@proxyhat\u002Fsdk&apos;); \u002F\u002F 仮想SDK例\n\nconst client = new ProxyHatClient({\n  gateway: &apos;gate.proxyhat.com&apos;,\n  port: 8080,\n  username: &apos;user&apos;,\n  password: &apos;pass&apos;,\n  country: &apos;JP&apos;,\n  rotation: &apos;per-request&apos;,  \u002F\u002F リクエストごとにIPローテーション\n  maxRetries: 3,\n  backoff: &apos;exponential&apos;,\n  timeout: 10000\n});\n\nasync function fetchOrderbookSDK(symbol) {\n  const url = `https:\u002F\u002Fapi.bybit.com\u002Fv5\u002Fmarket\u002Forderbook?category=spot&amp;symbol=${symbol}&amp;limit=50`;\n  const data = await client.get(url, {\n    headers: { &apos;Accept&apos;: &apos;application\u002Fjson&apos; }\n  });\n  if (data.retCode !== 0) {\n    throw new Error(`retCode=${data.retCode}, retMsg=${data.retMsg}`);\n  }\n  return data.result;\n}\n\n\u002F\u002F 複数銘柄を順次取得（レート制限を考慮してシーケンシャル）\nasync function scrapeAll(symbols) {\n  const results = [];\n  for (const sym of symbols) {\n    try {\n      const ob = await fetchOrderbookSDK(sym);\n      results.push({ symbol: sym, bestBid: ob.bids[0]?.[0], bestAsk: ob.asks[0]?.[0] });\n      console.log(`${sym}: bid=${ob.bids[0]?.[0]}, ask=${ob.asks[0]?.[0]}`);\n    } catch (err) {\n      console.error(`${sym}: ${err.message}`);\n    }\n    \u002F\u002F エンドポイント別レート予算: orderbook は 5 req\u002Fsec に制限\n    await new Promise(r =&gt; setTimeout(r, 200));\n  }\n  return results;\n}\n\nscrapeAll([&apos;BTCUSDT&apos;, &apos;ETHUSDT&apos;, &apos;SOLUSDT&apos;, &apos;XRPUSDT&apos;, &apos;DOGEUSDT&apos;]);\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Ch2>実装例3: Python (httpx) でklineデータのページネーション\u003C\u002Fh2>\n\n\u003Cp>klineデータの過去分を取得する場合、\u003Ccode>start\u003C\u002Fcode> と \u003Ccode>end\u003C\u002Fcode> パラメータで時間範囲を指定し、\u003Ccode>limit\u003C\u002Fcode>（最大1000件）でページネーションを行います。この場合、\u003Cstrong>sticky session\u003C\u002Fstrong>を使用することで、同一IPから継続的にアクセスし、IPローテーションによる一貫性の問題を回避できます。\u003C\u002Fp>\n\n\u003Cpre>\u003Ccode># ===== 生プロキシパターン (httpx) =====\nimport httpx\nimport asyncio\nimport time\nfrom datetime import datetime, timedelta, timezone\n\nPROXY_URL = &quot;http:\u002F\u002Fuser-country-JP-sid-kline01:pass@gate.proxyhat.com:8080&quot;\n\nBASE_URL = &quot;https:\u002F\u002Fapi.bybit.com\u002Fv5\u002Fmarket\u002Fkline&quot;\n\nasync def fetch_kline_page(symbol, category, interval, start_ts, end_ts, retries=3):\n    params = {\n        &quot;category&quot;: category,\n        &quot;symbol&quot;: symbol,\n        &quot;interval&quot;: str(interval),\n        &quot;start&quot;: str(start_ts),\n        &quot;end&quot;: str(end_ts),\n        &quot;limit&quot;: &quot;1000&quot;\n    }\n    for attempt in range(retries):\n        try:\n            async with httpx.AsyncClient(\n                proxy=PROXY_URL,\n                timeout=15.0,\n                headers={\n                    &quot;Accept&quot;: &quot;application\u002Fjson&quot;,\n                    &quot;User-Agent&quot;: &quot;Mozilla\u002F5.0 (compatible; KlineCollector\u002F1.0)&quot;\n                }\n            ) as client:\n                resp = await client.get(BASE_URL, params=params)\n                resp.raise_for_status()\n                data = resp.json()\n                if data.get(&quot;retCode&quot;) == 0:\n                    return data[&quot;result&quot;]\n                else:\n                    raise Exception(f&quot;retCode={data[&apos;retCode&apos;]}, retMsg={data[&apos;retMsg&apos;]}&quot;)\n        except Exception as e:\n            wait = 2 ** attempt * 500\n            print(f&quot;  [retry {attempt+1}\u002F{retries}] {e}, waiting {wait}ms&quot;)\n            if attempt == retries - 1:\n                raise\n            await asyncio.sleep(wait \u002F 1000)\n\nasync def scrape_kline_history(symbol, category, interval, days_back):\n    &quot;&quot;&quot;過去N日分のklineを1000件ずつページネーションで取得&quot;&quot;&quot;\n    now = int(datetime.now(timezone.utc).timestamp() * 1000)\n    start = int((datetime.now(timezone.utc) - timedelta(days=days_back)).timestamp() * 1000)\n    all_candles = []\n    cursor = start\n    \n    while cursor &lt; now:\n        end = min(cursor + (interval * 60_000 * 1000), now)  # 1000本分の時間窓\n        print(f&quot;Fetching {symbol} kline: {datetime.fromtimestamp(cursor\u002F1000, tz=timezone.utc)} -&gt; {datetime.fromtimestamp(end\u002F1000, tz=timezone.utc)}&quot;)\n        result = await fetch_kline_page(symbol, category, interval, cursor, end)\n        candles = result.get(&quot;list&quot;, [])\n        if not candles:\n            break\n        all_candles.extend(candles)\n        print(f&quot;  Got {len(candles)} candles (total: {len(all_candles)})&quot;)\n        # 最後のキャンドルのタイムスタンプ + 1ms から次ページ\n        cursor = int(candles[-1][0]) + 1\n        # レート予算: kline は 2 req\u002Fsec に制限\n        await asyncio.sleep(0.5)\n    \n    return all_candles\n\n# 実行例: BTCUSDT現物の1時間足を過去7日分取得\nasync def main():\n    candles = await scrape_kline_history(&quot;BTCUSDT&quot;, &quot;spot&quot;, 60, 7)\n    print(f&quot;\\nTotal candles collected: {len(candles)}&quot;)\n    if candles:\n        print(f&quot;First: ts={candles[0][0]}, open={candles[0][1]}&quot;)\n        print(f&quot;Last:  ts={candles[-1][0]}, close={candles[-1][4]}&quot;)\n\nasyncio.run(main())\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Cpre>\u003Ccode># ===== ProxyHat SDKパターン (Python) =====\nfrom proxyhat import ProxyHatClient  # 仮想SDK例\nimport asyncio\n\nasync def fetch_kline_sdk(symbol, category, interval, start_ts, end_ts):\n    client = ProxyHatClient(\n        gateway=&quot;gate.proxyhat.com&quot;,\n        port=8080,\n        username=&quot;user&quot;,\n        password=&quot;pass&quot;,\n        country=&quot;JP&quot;,\n        session=&quot;kline-pagination-01&quot;,  # sticky sessionでIP固定\n        max_retries=3,\n        backoff=&quot;exponential&quot;,\n        timeout=15.0\n    )\n    url = f&quot;https:\u002F\u002Fapi.bybit.com\u002Fv5\u002Fmarket\u002Fkline?category={category}&amp;symbol={symbol}&amp;interval={interval}&amp;start={start_ts}&amp;end={end_ts}&amp;limit=1000&quot;\n    data = await client.get_async(url)\n    if data.get(&quot;retCode&quot;) != 0:\n        raise Exception(f&quot;retCode={data[&apos;retCode&apos;]}, retMsg={data[&apos;retMsg&apos;]}&quot;)\n    return data[&quot;result&quot;]\n\nasync def scrape_with_sdk(symbol, category, interval, days_back):\n    from datetime import datetime, timedelta, timezone\n    now = int(datetime.now(timezone.utc).timestamp() * 1000)\n    start = int((datetime.now(timezone.utc) - timedelta(days=days_back)).timestamp() * 1000)\n    all_candles = []\n    cursor = start\n    while cursor &lt; now:\n        end = min(cursor + (interval * 60_000 * 1000), now)\n        result = await fetch_kline_sdk(symbol, category, interval, cursor, end)\n        candles = result.get(&quot;list&quot;, [])\n        if not candles:\n            break\n        all_candles.extend(candles)\n        cursor = int(candles[-1][0]) + 1\n        await asyncio.sleep(0.5)  # レート予算\n    return all_candles\n\nasyncio.run(scrape_with_sdk(&quot;ETHUSDT&quot;, &quot;spot&quot;, 60, 3))\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Ch2>実装例4: Python (aiohttp) でティッカー情報を高並列スクレイピング\u003C\u002Fh2>\n\n\u003Cp>複数銘柄のティッカー情報を高並列で取得する例です。エンドポイント別のレート予算を管理しつつ、ローテーションプロキシでIPを分散させます。\u003C\u002Fp>\n\n\u003Cpre>\u003Ccode># ===== 生プロキシパターン (aiohttp) =====\nimport aiohttp\nimport asyncio\nimport logging\nfrom aiohttp import ClientTimeout, ClientProxyConnectionError\n\nlogging.basicConfig(level=logging.INFO, format=&apos;%(asctime)s [%(levelname)s] %(message)s&apos;)\nlogger = logging.getLogger(&quot;bybit_scraper&quot;)\n\nPROXY = &quot;http:\u002F\u002Fuser-country-JP:pass@gate.proxyhat.com:8080&quot;\nBASE = &quot;https:\u002F\u002Fapi.bybit.com\u002Fv5\u002Fmarket\u002Ftickers&quot;\n\n# エンドポイント別レート予 budget (req\u002Fsec)\nRATE_BUDGETS = {\n    &quot;tickers&quot;: 3,   # 3 req\u002Fsec\n    &quot;orderbook&quot;: 5, # 5 req\u002Fsec\n    &quot;kline&quot;: 2,     # 2 req\u002Fsec\n}\n\nclass RateLimiter:\n    &quot;&quot;&quot;トークンバケット方式のレート制限&quot;&quot;&quot;\n    def __init__(self, rate_per_sec):\n        self.rate = rate_per_sec\n        self.tokens = rate_per_sec\n        self.last_refill = asyncio.get_event_loop().time()\n        self.lock = asyncio.Lock()\n    \n    async def acquire(self):\n        async with self.lock:\n            now = asyncio.get_event_loop().time()\n            elapsed = now - self.last_refill\n            self.tokens = min(self.rate, self.tokens + elapsed * self.rate)\n            self.last_refill = now\n            if self.tokens &lt; 1:\n                wait = (1 - self.tokens) \u002F self.rate\n                await asyncio.sleep(wait)\n                self.tokens = 0\n            else:\n                self.tokens -= 1\n\nclass CircuitBreaker:\n    &quot;&quot;&quot;連続エラー時のサーキットブレーカー&quot;&quot;&quot;\n    def __init__(self, threshold=5, reset_timeout=60):\n        self.failures = 0\n        self.threshold = threshold\n        self.reset_timeout = reset_timeout\n        self.opened_at = None\n    \n    def record_failure(self):\n        self.failures += 1\n        if self.failures &gt;= self.threshold:\n            self.opened_at = asyncio.get_event_loop().time()\n            logger.warning(f&quot;Circuit breaker OPEN after {self.failures} failures&quot;)\n    \n    def record_success(self):\n        self.failures = 0\n        self.opened_at = None\n    \n    def is_open(self):\n        if self.opened_at is None:\n            return False\n        elapsed = asyncio.get_event_loop().time() - self.opened_at\n        if elapsed &gt; self.reset_timeout:\n            logger.info(&quot;Circuit breaker resetting&quot;)\n            self.failures = 0\n            self.opened_at = None\n            return False\n        return True\n\nlimiter = RateLimiter(RATE_BUDGETS[&quot;tickers&quot;])\nbreaker = CircuitBreaker(threshold=5, reset_timeout=60)\n\nasync def fetch_tickers(session, category, retries=3):\n    if breaker.is_open():\n        raise Exception(&quot;Circuit breaker is open&quot;)\n    \n    url = f&quot;{BASE}?category={category}&quot;\n    for attempt in range(retries):\n        await limiter.acquire()\n        try:\n            async with session.get(url, timeout=ClientTimeout(total=10)) as resp:\n                if resp.status == 403:\n                    logger.warning(f&quot;403 on attempt {attempt+1} - rate limited or geo-blocked&quot;)\n                    breaker.record_failure()\n                    await asyncio.sleep(2 ** attempt)\n                    continue\n                resp.raise_for_status()\n                data = await resp.json()\n                if data.get(&quot;retCode&quot;) == 0:\n                    breaker.record_success()\n                    return data[&quot;result&quot;]\n                else:\n                    raise Exception(f&quot;retCode={data[&apos;retCode&apos;]}, retMsg={data[&apos;retMsg&apos;]}&quot;)\n        except (aiohttp.ClientError, asyncio.TimeoutError) as e:\n            logger.error(f&quot;Attempt {attempt+1} failed: {type(e).__name__}: {e}&quot;)\n            breaker.record_failure()\n            if attempt &lt; retries - 1:\n                await asyncio.sleep(2 ** attempt)\n            else:\n                raise\n\nasync def scrape_all_tickers(categories):\n    connector = aiohttp.TCPConnector(limit=20, limit_per_host=5)\n    timeout = ClientTimeout(total=30)\n    async with aiohttp.ClientSession(\n        connector=connector,\n        timeout=timeout,\n        headers={&quot;Accept&quot;: &quot;application\u002Fjson&quot;, &quot;User-Agent&quot;: &quot;Mozilla\u002F5.0 (compatible; TickerBot\u002F1.0)&quot;}\n    ) as session:\n        tasks = []\n        for cat in categories:\n            tasks.append(fetch_tickers(session, cat))\n        results = await asyncio.gather(*tasks, return_exceptions=True)\n        \n        for cat, result in zip(categories, results):\n            if isinstance(result, Exception):\n                logger.error(f&quot;{cat}: FAILED - {result}&quot;)\n            else:\n                tickers = result.get(&quot;list&quot;, [])\n                logger.info(f&quot;{cat}: {len(tickers)} tickers retrieved&quot;)\n                if tickers:\n                    first = tickers[0]\n                    logger.info(f&quot;  Sample: {first.get(&apos;symbol&apos;)} lastPrice={first.get(&apos;lastPrice&apos;)}&quot;)\n\nasyncio.run(scrape_all_tickers([&quot;spot&quot;, &quot;linear&quot;]))\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Ch2>実装例5: 直近の約定履歴を継続的にポーリング\u003C\u002Fh2>\n\n\u003Cp>\u003Ccode>\u002Fv5\u002Fmarket\u002Frecent-trade\u003C\u002Fcode> エンドポイントを使用して、直近の約定履歴を定期的にポーリングする例です。リクエストごとにIPをローテーションしつつ、重複データを除外します。\u003C\u002Fp>\n\n\u003Cpre>\u003Ccode># ===== Python (httpx) + ローテーションプロキシ =====\nimport httpx\nimport asyncio\nimport time\nimport json\n\n# リクエストごとに異なるセッションID = IPローテーション\ndef get_proxy_url(request_id):\n    return f&quot;http:\u002F\u002Fuser-country-JP-sid-rt{request_id}:pass@gate.proxyhat.com:8080&quot;\n\nBASE = &quot;https:\u002F\u002Fapi.bybit.com\u002Fv5\u002Fmarket\u002Frecent-trade&quot;\nseen_trade_ids = set()\nrequest_counter = 0\n\nasync def poll_recent_trades(symbol, category, interval_sec=2, max_polls=100):\n    global request_counter, seen_trade_ids\n    new_trades = []\n    \n    for poll_idx in range(max_polls):\n        request_counter += 1\n        proxy = get_proxy_url(request_counter)\n        params = {&quot;category&quot;: category, &quot;symbol&quot;: symbol, &quot;limit&quot;: &quot;50&quot;}\n        \n        try:\n            async with httpx.AsyncClient(\n                proxy=proxy,\n                timeout=10.0,\n                headers={&quot;Accept&quot;: &quot;application\u002Fjson&quot;}\n            ) as client:\n                resp = await client.get(BASE, params=params)\n                resp.raise_for_status()\n                data = resp.json()\n                \n                if data.get(&quot;retCode&quot;) != 0:\n                    print(f&quot;[poll {poll_idx}] retCode={data[&apos;retCode&apos;]}, retMsg={data[&apos;retMsg&apos;]}&quot;)\n                    await asyncio.sleep(interval_sec * 2)\n                    continue\n                \n                trades = data[&quot;result&quot;].get(&quot;list&quot;, [])\n                fresh = []\n                for t in trades:\n                    trade_id = t.get(&quot;execId&quot;, &quot;&quot;)\n                    if trade_id and trade_id not in seen_trade_ids:\n                        seen_trade_ids.add(trade_id)\n                        fresh.append(t)\n                \n                if fresh:\n                    new_trades.extend(fresh)\n                    print(f&quot;[poll {poll_idx}] {len(fresh)} new trades (total new: {len(new_trades)})&quot;)\n                    for ft in fresh[:3]:\n                        print(f&quot;  {ft.get(&apos;time&apos;)} price={ft.get(&apos;price&apos;)} qty={ft.get(&apos;size&apos;)} side={ft.get(&apos;side&apos;)}&quot;)\n                else:\n                    print(f&quot;[poll {poll_idx}] no new trades&quot;)\n        \n        except Exception as e:\n            print(f&quot;[poll {poll_idx}] ERROR: {type(e).__name__}: {e}&quot;)\n            await asyncio.sleep(interval_sec * 3)  # バックオフ\n            continue\n        \n        await asyncio.sleep(interval_sec)\n    \n    return new_trades\n\nasyncio.run(poll_recent_trades(&quot;BTCUSDT&quot;, &quot;spot&quot;, interval_sec=2, max_polls=30))\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Ch2>RESTスナップショット vs WebSocket orderbook.50ストリーム\u003C\u002Fh2>\n\n\u003Cp>Bybitは公開WebSocketチャンネルも提供しており、\u003Ccode>orderbook.50.{symbol}\u003C\u002Fcode> や \u003Ccode>orderbook.200.{symbol}\u003C\u002Fcode> でリアルタイムの板情報ストリームを購読できます。RESTのポーリング方式とWebSocket方式の比較は以下の通りです。\u003C\u002Fp>\n\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\u003Cth>項目\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>データ形式\u003C\u002Ftd>\u003Ctd>スナップショット（取得時点の完全な板）\u003C\u002Ftd>\u003Ctd>スナップショット＋差分更新\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>レイテンシ\u003C\u002Ftd>\u003Ctd>ポーリング間隔に依存（通常200ms〜2s）\u003C\u002Ftd>\u003Ctd>リアルタイム（通常50ms未満）\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>レート制限\u003C\u002Ftd>\u003Ctd>リクエストごとに消費\u003C\u002Ftd>\u003Ctd>接続ごと（購読後は追加リクエスト不要）\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>プロキシ要件\u003C\u002Ftd>\u003Ctd>リクエストごとのIPローテーションが可能\u003C\u002Ftd>\u003Ctd>WSS接続を維持（sticky session推奨）\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>適用ケース\u003C\u002Ftd>\u003Ctd>定期的なスナップショット保存、バッチ分析\u003C\u002Ftd>\u003Ctd>リアルタイムトレーディング、ライブダッシュボード\u003C\u002Ftd>\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\n\n\u003Cp>WebSocketを使用する場合、ProxyHatのSOCKS5プロキシ（\u003Ccode>gate.proxyhat.com:1080\u003C\u002Fcode>）とsticky sessionを組み合わせることで、安定したWSS接続を維持できます。\u003C\u002Fp>\n\n\u003Cpre>\u003Ccode># ===== WebSocket + SOCKS5 プロキシ (Node.js) =====\nconst WebSocket = require(&apos;ws&apos;);\nconst { SocksProxyAgent } = require(&apos;socks-proxy-agent&apos;);\n\n\u002F\u002F sticky session でIPを固定（WSS接続の安定性確保）\nconst socksAgent = new SocksProxyAgent(\n  &apos;socks5:\u002F\u002Fuser-country-JP-sid-ws01:pass@gate.proxyhat.com:1080&apos;\n);\n\nconst ws = new WebSocket(&apos;wss:\u002F\u002Fstream.bybit.com\u002Fv5\u002Fpublic\u002Fspot&apos;, {\n  agent: socksAgent\n});\n\nws.on(&apos;open&apos;, () =&gt; {\n  console.log(&apos;WebSocket connected via ProxyHat SOCKS5&apos;);\n  \u002F\u002F orderbook.50 ストリームを購読\n  ws.send(JSON.stringify({\n    op: &apos;subscribe&apos;,\n    args: [&apos;orderbook.50.BTCUSDT&apos;, &apos;orderbook.50.ETHUSDT&apos;]\n  }));\n});\n\nws.on(&apos;message&apos;, (data) =&gt; {\n  const msg = JSON.parse(data.toString());\n  if (msg.topic &amp;&amp; msg.topic.startsWith(&apos;orderbook.50&apos;)) {\n    const symbol = msg.topic.split(&apos;.&apos;).pop();\n    if (msg.type === &apos;snapshot&apos;) {\n      console.log(`[${symbol}] snapshot: ${msg.data.bids.length} bids, ${msg.data.asks.length} asks`);\n    } else if (msg.type === &apos;delta&apos;) {\n      console.log(`[${symbol}] delta: delete=${msg.data.delete?.length}, update=${msg.data.update?.length}, insert=${msg.data.insert?.length}`);\n    }\n  }\n});\n\nws.on(&apos;error&apos;, (err) =&gt; {\n  console.error(&apos;WebSocket error:&apos;, err.message);\n});\n\nws.on(&apos;close&apos;, () =&gt; {\n  console.log(&apos;WebSocket closed&apos;);\n});\n\n\u002F\u002F グレースフルシャットダウン\nprocess.on(&apos;SIGINT&apos;, () =&gt; {\n  ws.close();\n  process.exit(0);\n});\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Ch2>よくある失敗とエッジケース\u003C\u002Fh2>\n\n\u003Ch3>1. retCodeのチェック漏れ\u003C\u002Fh3>\n\n\u003Cp>HTTPステータス200でも \u003Ccode>retCode\u003C\u002Fcode> が非ゼロのケースがあります。必ずJSONボディの \u003Ccode>retCode\u003C\u002Fcode> を検証してください。\u003Ccode>retMsg\u003C\u002Fcode> には「rate limit exceeded」や「invalid symbol」などのメッセージが含まれます。\u003C\u002Fp>\n\n\u003Ch3>2. バーストアクセスによるIPバン\u003C\u002Fh3>\n\n\u003Cp>ループ内で \u003Ccode>await\u003C\u002Fcode> なしに連続リクエストを送ると、数秒で403と10分間のIPバンが発生します。レートリミッター（トークンバケット）を必ず実装してください。エンドポイント別のレート予算を分けることも重要です。\u003C\u002Fp>\n\n\u003Ch3>3. 地域制限の見落とし\u003C\u002Fh3>\n\n\u003Cp>データセンタープロキシを使用して「アクセスできるのにデータが返ってこない」場合は、CloudFrontレベルでジオブロックされている可能性があります。\u003Ccode>user-country-JP\u003C\u002Fcode> などのジオターゲティングフラグで許可された国を指定してください。\u003C\u002Fp>\n\n\u003Ch3>4. kline ページネーションでの時刻の扱い\u003C\u002Fh3>\n\n\u003Cp>Bybitのklineエンドポイントは \u003Ccode>start\u003C\u002Fcode> と \u003Ccode>end\u003C\u002Fcode> をミリ秒タイムスタンプで受け取ります。ページネーション時は最後のキャンドルのタイムスタンプ +1ms を次の \u003Ccode>start\u003C\u002Fcode> に設定してください。intervalパラメータは分単位の整数（1, 5, 15, 30, 60, 240, 720, D, W, M）です。\u003C\u002Fp>\n\n\u003Ch3>5. プロキシ認証エラー\u003C\u002Fh3>\n\n\u003Cp>ユーザー名にジオターゲティングフラグやセッションフラグを含める場合、コロン（\u003Ccode>:\u003C\u002Fcode>）で区切る必要があります。形式は \u003Ccode>user-country-JP-sid-abc123\u003C\u002Fcode> です。パスワードに特殊文字が含まれる場合はURLエンコードしてください。\u003C\u002Fp>\n\n\u003Ch2>ProxyHat固有のセットアップとベストプラクティス\u003C\u002Fh2>\n\n\u003Cp>ProxyHatを使用したBybit APIスクレイピングのベストプラクティスをまとめます。\u003C\u002Fp>\n\n\u003Cul>\n\u003Cli>エンドポイント別レート予算: \u003Ccode>orderbook\u003C\u002Fcode> は5 req\u002Fsec、\u003Ccode>tickers\u003C\u002Fcode> は3 req\u002Fsec、\u003Ccode>kline\u003C\u002Fcode> は2 req\u002Fsecを目安に設定。\u003C\u002Fli>\n\u003Cli>per-request ローテーション: 高頻度ポーリングにはリクエストごとにIPを変える \u003Ccode>user-sid-{unique_id}\u003C\u002Fcode> パターンを使用。\u003C\u002Fli>\n\u003Cli>sticky session: klineページネーションやWebSocket接続では \u003Ccode>user-sid-abc123\u003C\u002Fcode> でIPを固定。\u003C\u002Fli>\n\u003Cli>指数バックオフ: 403または \u003Ccode>retCode\u003C\u002Fcode> 非ゼロ時は2^attempt * 500msでリトライ。\u003C\u002Fli>\n\u003Cli>サーキットブレーカー: 連続5回失敗で60秒間リクエストを停止し、IPバンの延長を防ぐ。\u003C\u002Fli>\n\u003Cli>ジオターゲティング: \u003Ccode>user-country-JP\u003C\u002Fcode> または \u003Ccode>user-country-SG\u003C\u002Fcode> で許可された国からアクセス。\u003C\u002Fli>\n\u003Cli>タイムアウト: プロキシ経由のレイテンシを考慮し、10〜15秒のタイムアウトを設定。\u003C\u002Fli>\n\u003C\u002Ful>\n\n\u003Cp>詳細なプロキシ設定については\u003Ca href=\"https:\u002F\u002Fdocs.proxyhat.com\u002F\" rel=\"noopener noreferrer\">ProxyHatドキュメント\u003C\u002Fa>を参照してください。ウェブスクレイピングのユースケースについては\u003Ca href=\"\u002Fja\u002Fuse-cases\u002Fweb-scraping\">こちら\u003C\u002Fa>を、SERPトラッキングについては\u003Ca href=\"\u002Fja\u002Fuse-cases\u002Fserp-tracking\">こちら\u003C\u002Fa>を参照してください。\u003C\u002Fp>\n\n\u003Ch2>Key Takeaways（重要ポイント）\u003C\u002Fh2>\n\n\u003Cblockquote>\n\u003Cul>\n\u003Cli>Bybit V5 Market APIは \u003Ccode>category\u003C\u002Fcode> パラメータで spot\u002Flinear\u002Finverse\u002Foption を切り替え、統一された retCode\u002FretMsg エンベロープでレスポンスを返す。\u003C\u002Fli>\n\u003Cli>IPベースのレート制限はエンドポイントごとに設定され、超過すると403と約10分間のIPバンが発生する。\u003C\u002Fli>\n\u003Cli>地理的制限はCloudFrontレベルで実装され、米国・英国・制限地域からのアクセスがブロックされる。住宅プロキシのジオターゲティングで回避可能。\u003C\u002Fli>\n\u003Cli>ローテーションプロキシ（\u003Ccode>gate.proxyhat.com:8080\u003C\u002Fcode>）でリクエストごとにIPを変えることで、各IPのレート制限クォータを独立消費できる。\u003C\u002Fli>\n\u003Cli>Sticky session（\u003Ccode>-sid-abc123\u003C\u002Fcode>）はklineページネーションやWebSocket接続の安定性に不可欠。\u003C\u002Fli>\n\u003Cli>REST vs WebSocketの選択は用途次第。定期的なスナップショット保存はREST、リアルタイムトレーディングはWebSocket（SOCKS5 \u003Ccode>:1080\u003C\u002Fcode>）。\u003C\u002Fli>\n\u003Cli>本ガイドのプロキシ設定: HTTPは \u003Ccode>gate.proxyhat.com:8080\u003C\u002Fcode>、SOCKS5は \u003Ccode>gate.proxyhat.com:1080\u003C\u002Fcode>。ユーザー名に \u003Ccode>country-JP\u003C\u002Fcode> や \u003Ccode>sid-xxx\u003C\u002Fcode> フラグを指定。\u003C\u002Fli>\n\u003C\u002Ful>\n\u003C\u002Fblockquote>\n\n\u003Cp>Bybit V5 Market APIのスクレイピングは、適切なプロキシインフラとレート管理があれば、安定した市場データパイプラインを構築できます。ProxyHatのローテーションプロキシを活用し、エンドポイント別のレート予算と指数バックオフを組み合わせることで、403バンや地理的制限を回避しながら高品質なデータ収集が可能になります。\u003Ca href=\"\u002Fja\u002Fpricing\">ProxyHatのプラン\u003C\u002Fa>を確認し、今すぐBybit市場データの収集を始めましょう。\u003C\u002Fp>","暗号資産の市場データをプロキシで収集（Bybit V5の例） | ProxyHat","Bybit V5 Market APIをローテーションプロキシでスクレイピングする方法を解説。orderbook・tickers・klineエンドポイント、レート制限回避、地域制限対策をコード例付きで紹介。","\u002Fja\u002Fblog\u002Fbybit-v5-market-api-proxy-scraping",null,"暗号資産の市場データ収集ガイド | ProxyHat","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fja\u002Fbybit-v5-market-api-proxy-scraping-og.webp",[18,21,24],{"question":19,"answer":20},"なぜBybit APIスクレイピングでプロキシが重要なのですか？","BybitはエンドポイントごとにIPベースのレート制限を設けており、制限超過で403レスポンスと約10分間のIPバンが発生します。また、米国・英国などの地域制限によりCloudFront経由でアクセスがブロックされる場合があります。ローテーションプロキシを使うことで、これらの制限を回避し、安定したデータ収集が可能になります。",{"question":22,"answer":23},"Bybit APIスクレイピングに最適なプロキシタイプは何ですか？","Bybitの地理的制限を回避するには、住宅プロキシ（Residential Proxy）が最適です。データセンタープロキシは高速ですが、CloudFrontの geo-block に検出されやすい傾向があります。住宅プロキシは実際のISP IPアドレスを使用するため、ブロックされるリスクが低く、国・都市レベルのジオターゲティングも可能です。",{"question":25,"answer":26},"Bybit APIスクレイピングでブロックを回避するにはどうすればよいですか？","リクエストごとのIPローテーション、エンドポイント別のレート予算管理、指数バックオフ付きリトライ、適切なUser-AgentとAcceptヘッダーの設定、そして許可された国からの住宅プロキシの使用を組み合わせることで、ブロックを大幅に減らすことができます。また、robots.txtとBybitの利用規約を遵守することが重要です。",false,"2026-08-03T16:09:16+00:00","2026-10-04T01:29:51+00:00","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fja\u002Fbybit-v5-market-api-proxy-scraping-master.webp","How to Scrape the Bybit V5 Market API with Rotating Proxies","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fja\u002Fbybit-v5-market-api-proxy-scraping-card.webp",12,{"name":35,"slug":36,"bio":37,"avatar_url":14,"website_url":14,"social_links":14},"ProxyHat Team","proxyhat-team","The ProxyHat editorial team covers proxies, web scraping, and data extraction.",[39],{"id":40,"slug":41,"name":42,"description":14,"meta_title":43,"meta_description":44,"parent_id":14},4,"kaihatsusha-gaido","開発者ガイド","開発者ガイド | ProxyHat ブログ","プロキシをアプリケーションに統合するためのコードチュートリアルとSDKガイド。",[],{"de":47,"fr":48,"pt":49,"ru":50,"zh":51,"pl":52,"ko":53,"it":54,"es":55,"en":56,"ja":13,"x-default":56},"\u002Fde\u002Fblog\u002Fbybit-v5-market-api-mit-rotating-proxies-scrapen","\u002Ffr\u002Fblog\u002Fscraper-api-bybit-v5-proxys-rotatifs","\u002Fpt\u002Fblog\u002Fcomo-raspar-bybit-v5-market-api-proxies","\u002Fru\u002Fblog\u002Fkak-skrejpit-bybit-v5-market-api","\u002Fcn\u002Fblog\u002Fscrape-bybit-v5-market-api-proxy","\u002Fpl\u002Fblog\u002Fjak-scrapowac-bybit-v5-api-proxy","\u002Fko\u002Fblog\u002Fbybit-v5-market-api-proxy-scraping","\u002Fit\u002Fblog\u002Fscrape-bybit-v5-market-api-proxy","\u002Fes\u002Fblog\u002Fscrapear-api-mercado-bybit-v5-proxies","\u002Fblog\u002Fscrape-bybit-v5-market-api-rotating-proxies",{"de":47,"fr":48,"pt":49,"ru":50,"zh":51,"pl":52,"ko":53,"it":54,"es":55,"en":56,"ja":13,"tr":58},"\u002Ftr\u002Fblog\u002Fbybit-v5-market-api-dondurulen-proxy",87,[61,77,92,108],{"id":62,"slug":63,"title":64,"excerpt":65,"featured_image_url":66,"featured_image_alt":67,"card_image_url":68,"og_image_url":69,"published_at":70,"updated_at":70,"content_updated_at":71,"reading_time_minutes":33,"is_featured":27,"indexable":4,"views":72,"author":73,"categories":74,"tags":76},176,"got-scraping-nodejs-purokishi","Node.jsでgot-scrapingを使ったプロキシ連携の完全ガイド","got-scrapingのheader-generatorとProxyHatレジデンシャルプロキシを組み合わせ、Node.jsでブロックされないスクレイピングを構築する方法を解説。実践的なコード例付き。","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fja\u002Fgot-scraping-nodejs-purokishi-master.webp","got-scraping in Node.js: A Developer's Guide with Residential Proxies","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fja\u002Fgot-scraping-nodejs-purokishi-card.webp","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fja\u002Fgot-scraping-nodejs-purokishi-og.webp","2026-08-04T16:05:06+00:00","2026-10-03T08:57:49+00:00",121,{"name":35,"slug":36,"bio":37,"avatar_url":14,"website_url":14,"social_links":14},[75],{"id":40,"slug":41,"name":42,"description":14,"meta_title":43,"meta_description":44,"parent_id":14},[],{"id":78,"slug":79,"title":80,"excerpt":81,"featured_image_url":82,"featured_image_alt":83,"card_image_url":84,"og_image_url":85,"published_at":86,"updated_at":86,"content_updated_at":71,"reading_time_minutes":33,"is_featured":27,"indexable":27,"views":87,"author":88,"categories":89,"tags":91},175,"colly-purokushi-roteshon-gaido","Collyでのローテーティングプロキシ完全ガイド: Goスクレイパーの本番運用","Collyでのローテーティングプロキシの実装方法を解説。RoundRobinProxySwitcherとカスタムプロキシ関数でResidentialプロキシをリクエストごとに切り替え、ブロック回避と高スループットを実現する実践的なGoコード例を提供します。","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fja\u002Fcolly-purokushi-roteshon-gaido-master.webp","Rotating Proxies in Colly: A Framework-Idiomatic Guide for Go Developers","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fja\u002Fcolly-purokushi-roteshon-gaido-card.webp","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fja\u002Fcolly-purokushi-roteshon-gaido-og.webp","2026-08-04T10:05:34+00:00",71,{"name":35,"slug":36,"bio":37,"avatar_url":14,"website_url":14,"social_links":14},[90],{"id":40,"slug":41,"name":42,"description":14,"meta_title":43,"meta_description":44,"parent_id":14},[],{"id":93,"slug":94,"title":95,"excerpt":96,"featured_image_url":97,"featured_image_alt":98,"card_image_url":99,"og_image_url":100,"published_at":101,"updated_at":101,"content_updated_at":102,"reading_time_minutes":33,"is_featured":27,"indexable":27,"views":103,"author":104,"categories":105,"tags":107},194,"binance-api-scraping-proxy","Binance REST APIをプロキシでスクレイピングする完全ガイド","Binanceの公開マーケットデータREST APIをプロキシ経由で大規模収集する方法を、エンドポイント別のウェイト制限、IPローテーション、リトライ戦略まで含めて解説します。","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fja\u002Fbinance-api-scraping-proxy-master.webp","How to Scrape the Binance REST API with Proxies: A Developer Guide","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fja\u002Fbinance-api-scraping-proxy-card.webp","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fja\u002Fbinance-api-scraping-proxy-og.webp","2026-08-03T10:04:04+00:00","2026-10-03T08:21:25+00:00",82,{"name":35,"slug":36,"bio":37,"avatar_url":14,"website_url":14,"social_links":14},[106],{"id":40,"slug":41,"name":42,"description":14,"meta_title":43,"meta_description":44,"parent_id":14},[],{"id":109,"slug":110,"title":111,"excerpt":112,"featured_image_url":113,"featured_image_alt":114,"card_image_url":115,"og_image_url":116,"published_at":117,"updated_at":117,"content_updated_at":118,"reading_time_minutes":33,"is_featured":27,"indexable":27,"views":119,"author":120,"categories":121,"tags":123},172,"swift-urlsession-proxy-guide","Swiftでプロキシを使用する完全ガイド：URLSessionで residential プロキシを活用する方法","iOS・macOS開発者向けに、SwiftのURLSessionでresidentialプロキシを設定・認証・活用する実践的なコードファーストガイド。ProxyHatゲートウェイを使ったHTTP\u002FSOCKS5構成、async\u002Fawait並行処理、本番運用のベストプラクティスまで網羅。","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fja\u002Fswift-urlsession-proxy-guide-master.webp","Using Proxies in Swift: A Code-First Guide to URLSession, SOCKS5 & Residential IPs","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fja\u002Fswift-urlsession-proxy-guide-card.webp","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fja\u002Fswift-urlsession-proxy-guide-og.webp","2026-07-26T16:03:44+00:00","2026-10-03T23:53:00+00:00",230,{"name":35,"slug":36,"bio":37,"avatar_url":14,"website_url":14,"social_links":14},[122],{"id":40,"slug":41,"name":42,"description":14,"meta_title":43,"meta_description":44,"parent_id":14},[],[]]