[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"blog-post-ko-bybit-v5-market-api-proxy-scraping":3},{"success":4,"payload":5,"related":60,"errors":153},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 Market API 사례)","Bybit V5 Market API의 orderbook, tickers, kline, recent-trade 엔드포인트를 회전 프록시로 안정적으로 수집하는 개발자 가이드입니다. IP 레이트 리밋, 지역 제한, ProxyHat SDK 예제를 포함합니다.","\u003Cp>\u003Cstrong>면책 조항:\u003C\u002Fstrong> 이 글은 Bybit의 공개 마켓 데이터 엔드포인트를 기술적으로 설명할 뿐, Bybit 이용약관(TOS)을 위반하거나 거래소의 지적재산권을 침해하도록 조장하지 않습니다. 공개 데이터라도 robots.txt와 TOS를 확인하고 합리적인 요청 속도를 유지하세요.\u003C\u002Fp>\n\u003Cp>Bybit V5 Market API를 회전 프록시로 스크랩하는 방법(\u003Ccode>bybit v5 market api proxy\u003C\u002Fcode>)을 찾는 개발자들이 가장 먼저 부딪히는 문제는 두 가지입니다. 첫째, \u003Ccode>api.bybit.com\u002Fv5\u002Fmarket\u002Forderbook\u003C\u002Fcode>과 \u003Ccode>api.bybit.com\u002Fv5\u002Fmarket\u002Ftickers\u003C\u002Fcode>에 버스트 요청을 보내면 \u003Ccode>403\u003C\u002Fcode>과 함께 약 10분간 IP가 차단됩니다. 둘째, 미국\u002F영국 등 제한 지역에서는 Bybit 본사의 거리 기반 차단과 CloudFront 엣지 차단이 겹쳐 \u003Ccode>403\u003C\u002Fcode> 또는 \u003Ccode>451\u003C\u002Fcode>이 반환됩니다. 본 가이드는 Node.js와 Python에서 \u003Ccode>gate.proxyhat.com:8080\u003C\u002Fcode>(HTTP) 및 \u003Ccode>:1080\u003C\u002Fcode>(SOCKS5)을 통해 이 두 문제를 해결하는 실전 코드를 제공합니다.\u003C\u002Fp>\n\u003Ch2>Bybit V5 Market API 엔드포인트 개요\u003C\u002Fh2>\n\u003Cp>Bybit V5는 2023년에 출시된 통합 API로, 스팟(spot), 선물(linear), 인버스(inverse), 옵션(option)을 단일 엔드포인트 체계로 묶었습니다. 공개 마켓 데이터는 \u003Ccode>\u002Fv5\u002Fmarket\u002F\u003C\u002Fcode> 경로 아래에 있으며, 모두 \u003Ccode>category\u003C\u002Fcode> 파라미터로 자산군을 구분합니다. 자세한 스펙은 Bybit V5 공식 문서를 참고하세요.\u003C\u002Fp>\n\u003Ctable>\n\u003Cthead>\u003Ctr>\u003Cth>엔드포인트\u003C\u002Fth>\u003Cth>필수 파라미터\u003C\u002Fth>\u003Cth>주요 옵션\u003C\u002Fth>\u003Cth>용도\u003C\u002Fth>\u003C\u002Ftr>\u003C\u002Fthead>\n\u003Ctbody>\n\u003Ctr>\u003Ctd>\u003Ccode>GET \u002Fv5\u002Fmarket\u002Forderbook\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>\u003Ccode>category\u003C\u002Fcode>, \u003Ccode>symbol\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>\u003Ccode>limit\u003C\u002Fcode>(spot\u002Flinear: 1–200, 옵션: 25)\u003C\u002Ftd>\u003Ctd>실시간 호가창 스냅샷\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>\u003Ccode>GET \u002Fv5\u002Fmarket\u002Ftickers\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>\u003Ccode>category\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>\u003Ccode>symbol\u003C\u002Fcode>(선택)\u003C\u002Ftd>\u003Ctd>전체\u002F단일 티커 24h 통계\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>\u003Ccode>GET \u002Fv5\u002Fmarket\u002Fkline\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>\u003Ccode>category\u003C\u002Fcode>, \u003Ccode>symbol\u003C\u002Fcode>, \u003Ccode>interval\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>\u003Ccode>start\u003C\u002Fcode>, \u003Ccode>end\u003C\u002Fcode>, \u003Ccode>limit\u003C\u002Fcode>(최대 1000)\u003C\u002Ftd>\u003Ctd>과거 캔들 데이터 페이지네이션\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>\u003Ccode>GET \u002Fv5\u002Fmarket\u002Frecent-trade\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>\u003Ccode>category\u003C\u002Fcode>, \u003Ccode>symbol\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>\u003Ccode>limit\u003C\u002Fcode>(최대 1000)\u003C\u002Ftd>\u003Ctd>최근 체결 내역\u003C\u002Ftd>\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\n\u003Cp>\u003Ccode>category\u003C\u002Fcode>는 \u003Ccode>spot\u003C\u002Fcode>, \u003Ccode>linear\u003C\u002Fcode>, \u003Ccode>inverse\u003C\u002Fcode>, \u003Ccode>option\u003C\u002Fcode> 중 하나입니다. 응답은 다음과 같은 봉투(envelope)로 옵니다:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>{\n  &quot;retCode&quot;: 0,\n  &quot;retMsg&quot;: &quot;OK&quot;,\n  &quot;result&quot;: { \u002F* 실제 데이터 *\u002F },\n  &quot;time&quot;: 1700000000000\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>\u003Ccode>retCode\u003C\u002Fcode>가 \u003Ccode>0\u003C\u002Fcode>이면 성공, 그 외 값은 에러입니다. \u003Ccode>retMsg\u003C\u002Fcode>는 사람이 읽을 수 있는 메시지이며, 레이트 리밋 위반 시 \u003Ccode>retMsg\u003C\u002Fcode>에 \u003Ccode>rate limit\u003C\u002Fcode> 문자열이 포함되거나 HTTP \u003Ccode>403\u003C\u002Fcode>이 반환됩니다. HTTP 상태 코드만 보지 말고 반드시 \u003Ccode>retCode\u003C\u002Fcode>를 먼저 점검하세요.\u003C\u002Fp>\n\u003Ch2>IP 기반 레이트 리밋과 차단 창\u003C\u002Fh2>\n\u003Cp>Bybit는 엔드포인트별로 IP 기반 레이트 리밋을 적용합니다. 공식 문서에 따르면 \u003Ccode>\u002Fv5\u002Fmarket\u002Forderbook\u003C\u002Fcode>은 약 \u003Cstrong>600회\u002F5초\u003C\u002Fstrong> 수준의 캡을 가지며, \u003Ccode>\u002Fv5\u002Fmarket\u002Ftickers\u003C\u002Fcode>는 더 넉넉합니다(정확 수치는 Bybit가 업데이트하므로 문서를 확인하세요). 버스트 요청이 캡을 초과하면 \u003Cstrong>403\u003C\u002Fstrong>이 반환되고, 동일 IP는 약 \u003Cstrong>10분\u003C\u002Fstrong> 동안 추가 요청이 거부됩니다. 이는 Binance의 분 단위 가중치 모델과 달리 \u003Cstrong>차단 창(ban window)\u003C\u002Fstrong> 방식에 가깝습니다.\u003C\u002Fp>\n\u003Cp>회전 프록시가 없다면 단일 서버 IP로 여러 심볼의 오더북을 폴링하는 것만으로도 몇 초 안에 차단됩니다. 회전 프록시는 요청마다 출발 IP를 바꿔 각 IP의 카운터를 분산시키지만, 프록시 풀의 IP 다양성이 충분하지 않으면 동일 IP가 반복 사용되어 결국 차단됩니다. 따라서 레즈iden셜 프록시(수백만 IP 풀)가 데이터센터 프록시(수만 IP)보다 훨씬 안전합니다.\u003C\u002Fp>\n\u003Ch2>지역 제한과 CloudFront 차단\u003C\u002Fh2>\n\u003Cp>Bybit는 미국, 영국, 싱가포르 등 일부 지역에서 서비스를 제한하고 있으며, 제한 지역 IP에서 API 호출 시 403 또는 451이 반환됩니다. 또한 Bybit는 CloudFront를 사용하므로 엣지 노드 단에서 차단될 수도 있습니다. 자세한 제한 지역 목록은 Bybit 서비스 제한 국가 문서를 참고하세요.\u003C\u002Fp>\n\u003Cp>해결책은 Bybit가 허용하는 국가의 IP로 요청을 보내는 것입니다. ProxyHat은 사용자명에 \u003Ccode>-country-XX\u003C\u002Fcode> 형식으로 국가를 지정할 수 있습니다:\u003C\u002Fp>\n\u003Cpre>\u003Ccode># HTTP (기본 포트 8080)\ncurl -x http:\u002F\u002Fuser-country-DE:pass@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# SOCKS5 (포트 1080)\ncurl -x socks5:\u002F\u002Fuser-country-DE:pass@gate.proxyhat.com:1080 \\\n  &quot;https:\u002F\u002Fapi.bybit.com\u002Fv5\u002Fmarket\u002Ftickers?category=linear&quot;\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>독일(\u003Ccode>DE\u003C\u002Fcode>), 일본(\u003Ccode>JP\u003C\u002Fcode>), 한국(\u003Ccode>KR\u003C\u002Fcode>) 등은 일반적으로 허용되지만, 정책은 변경될 수 있으므로 \u003Ca href=\"\u002Fko\u002Flocations\">ProxyHat 로케이션 목록\u003C\u002Fa>에서 최신 지원 국가를 확인하고, 실제 배포 전에 해당 국가 IP로 테스트하세요.\u003C\u002Fp>\n\u003Ch2>Node.js (axios) 회전 IP 예제\u003C\u002Fh2>\n\u003Cp>먼저 원시 프록시(raw proxy) 방식과 ProxyHat SDK 방식을 나란히 보여줍니다. SDK는 인증 문자열 빌더, 세션 관리, 재시도를 캡슐화합니다.\u003C\u002Fp>\n\u003Ch3>원시 프록시 — 매 요청마다 세션 ID로 IP 회전\u003C\u002Fh3>\n\u003Cpre>\u003Ccode>\u002F\u002F raw-proxy.js\nconst axios = require(&apos;axios&apos;);\nconst { HttpsProxyAgent } = require(&apos;https-proxy-agent&apos;);\n\nconst GATE = &apos;gate.proxyhat.com&apos;;\nconst PORT = 8080;\nconst USER = &apos;user&apos;;\nconst PASS = &apos;pass&apos;;\nconst COUNTRY = &apos;DE&apos;;\n\nconst symbols = [&apos;BTCUSDT&apos;, &apos;ETHUSDT&apos;, &apos;SOLUSDT&apos;, &apos;XRPUSDT&apos;, &apos;DOGEUSDT&apos;];\n\nfunction buildAgent(sessionId) {\n  const proxyUrl = `http:\u002F\u002F${USER}-country-${COUNTRY}-sid-${sessionId}:${PASS}@${GATE}:${PORT}`;\n  return new HttpsProxyAgent(proxyUrl);\n}\n\nasync function fetchOrderbook(symbol, attempt = 0) {\n  if (attempt &gt;= 5) throw new Error(`${symbol} max retries exceeded`);\n  const sessionId = `${symbol}-${Date.now()}`;\n  try {\n    const res = await axios.get(&apos;https:\u002F\u002Fapi.bybit.com\u002Fv5\u002Fmarket\u002Forderbook&apos;, {\n      params: { category: &apos;spot&apos;, symbol, limit: 50 },\n      httpsAgent: buildAgent(sessionId),\n      timeout: 8000,\n    });\n    if (res.data.retCode !== 0) throw new Error(`retCode ${res.data.retCode}: ${res.data.retMsg}`);\n    return res.data.result;\n  } catch (err) {\n    const status = err.response?.status;\n    if (status === 403 || status === 429) {\n      const backoff = Math.min(1000 * Math.pow(2, attempt), 16000);\n      console.warn(`${symbol} ${status}, retry in ${backoff}ms`);\n      await new Promise(r =&gt; setTimeout(r, backoff));\n      return fetchOrderbook(symbol, attempt + 1);\n    }\n    throw err;\n  }\n}\n\n(async () =&gt; {\n  for (const sym of symbols) {\n    try {\n      const ob = await fetchOrderbook(sym);\n      console.log(sym, &apos;bid0&apos;, ob.b[0]?.[0], &apos;ask0&apos;, ob.a[0]?.[0]);\n    } catch (e) { console.error(sym, e.message); }\n    await new Promise(r =&gt; setTimeout(r, 200)); \u002F\u002F 엔드포인트당 자체 속도 제한\n  }\n})();\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>ProxyHat SDK — 인증\u002F세션 추상화\u003C\u002Fh3>\n\u003Cpre>\u003Ccode>\u002F\u002F proxyhat-sdk.js\nconst axios = require(&apos;axios&apos;);\nconst { HttpsProxyAgent } = require(&apos;https-proxy-agent&apos;);\nconst { ProxyHat } = require(&apos;@proxyhat\u002Fsdk&apos;); \u002F\u002F 예시 SDK, 실제 패키지명은 docs 확인\n\nconst hat = new ProxyHat({\n  user: &apos;user&apos;,\n  password: &apos;pass&apos;,\n  country: &apos;DE&apos;,\n  gateway: &apos;gate.proxyhat.com&apos;,\n  httpPort: 8080,\n});\n\nasync function fetchTickers(category) {\n  const agent = hat.httpAgent({ session: `tickers-${Date.now()}` });\n  try {\n    const res = await axios.get(&apos;https:\u002F\u002Fapi.bybit.com\u002Fv5\u002Fmarket\u002Ftickers&apos;, {\n      params: { category },\n      httpsAgent: agent,\n      timeout: 8000,\n    });\n    if (res.data.retCode !== 0) throw new Error(res.data.retMsg);\n    return res.data.result.list;\n  } catch (err) {\n    if (err.response?.status === 403) {\n      await hat.rotateSession();\n      return fetchTickers(category);\n    }\n    throw err;\n  }\n}\n\n(async () =&gt; {\n  const tickers = await fetchTickers(&apos;linear&apos;);\n  console.log(`linear tickers: ${tickers.length} symbols`);\n})();\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>SDK는 \u003Ccode>hat.httpAgent({ session })\u003C\u002Fcode> 호출마다 새 세션 ID를 생성해 출발 IP를 바꿉니다. \u003Ccode>403\u003C\u002Fcode> 시 \u003Ccode>hat.rotateSession()\u003C\u002Fcode>으로 즉시 회전할 수 있습니다. SDK 설치와 최신 옵션은 \u003Ca href=\"https:\u002F\u002Fdocs.proxyhat.com\u002F\" rel=\"noopener noreferrer\">ProxyHat 문서\u003C\u002Fa>를 참고하세요.\u003C\u002Fp>\n\u003Ch2>Python 예제 — kline 페이지네이션과 스티키 세션\u003C\u002Fh2>\n\u003Cp>kline은 \u003Ccode>start\u003C\u002Fcode>\u002F\u003Ccode>end\u003C\u002Fcode> 타임스탬프로 페이지네이션합니다. 한 페이지당 최대 1000개 캔들입니다. 페이지네이션 도중 IP가 바뀌면 Bybit 측에서 IP 일관성 검사를 할 수 있으므로, 단일 페이지네이션 시퀀스는 스티키 세션으로 동일 IP를 유지하는 것이 안전합니다. 시퀀스가 끝나면 세션을 바꿔 다음 심볼로 넘어갑니다.\u003C\u002Fp>\n\u003Cpre>\u003Ccode># kline_paginate.py\nimport requests\nimport time\nfrom requests.adapters import HTTPAdapter\nfrom urllib3.util.retry import Retry\n\nclass ProxyHatSession:\n    def __init__(self, user, password, country=&apos;DE&apos;, sticky_id=None):\n        self.user = user\n        self.password = password\n        self.country = country\n        self.sticky_id = sticky_id\n\n    def proxy_url(self, session_id=None):\n        sid = session_id or self.sticky_id or f&apos;py-{int(time.time())}&apos;\n        auth = f&apos;{self.user}-country-{self.country}-sid-{sid}:{self.password}&apos;\n        return f&apos;http:\u002F\u002F{auth}@gate.proxyhat.com:8080&apos;\n\n    def requests_session(self, session_id=None):\n        s = requests.Session()\n        s.proxies = {&apos;http&apos;: self.proxy_url(session_id), &apos;https&apos;: self.proxy_url(session_id)}\n        retry = Retry(total=4, backoff_factor=1.5,\n                      status_forcelist=[429, 500, 502, 503, 504],\n                      allowed_methods=[&apos;GET&apos;])\n        s.mount(&apos;https:\u002F\u002F&apos;, HTTPAdapter(max_retries=retry))\n        return s\n\ndef fetch_kline(symbol, category=&apos;spot&apos;, interval=&apos;60&apos;, start_ms=None, end_ms=None, limit=1000):\n    ph = ProxyHatSession(user=&apos;user&apos;, password=&apos;pass&apos;, country=&apos;DE&apos;,\n                         sticky_id=f&apos;kline-{symbol}&apos;)\n    s = ph.requests_session()\n    url = &apos;https:\u002F\u002Fapi.bybit.com\u002Fv5\u002Fmarket\u002Fkline&apos;\n    params = {&apos;category&apos;: category, &apos;symbol&apos;: symbol, &apos;interval&apos;: interval,\n              &apos;limit&apos;: limit}\n    if start_ms: params[&apos;start&apos;] = start_ms\n    if end_ms: params[&apos;end&apos;] = end_ms\n    try:\n        r = s.get(url, params=params, timeout=8)\n        data = r.json()\n        if data.get(&apos;retCode&apos;) != 0:\n            raise RuntimeError(f&quot;retCode {data.get(&apos;retCode&apos;)}: {data.get(&apos;retMsg&apos;)}&quot;)\n        return data[&apos;result&apos;][&apos;list&apos;]\n    except requests.HTTPError as e:\n        if r.status_code == 403:\n            print(f&apos;403 on {symbol}, IP may be banned ~10min; rotate&apos;)\n        raise\n\nif __name__ == &apos;__main__&apos;:\n    # 1시간봉, 가장 최근 1000개\n    now_ms = int(time.time() * 1000)\n    candles = fetch_kline(&apos;BTCUSDT&apos;, interval=&apos;60&apos;, end_ms=now_ms)\n    print(f&apos;BTCUSDT 1h candles: {len(candles)}&apos;)\n    oldest = int(candles[-1][0])\n    # 다음 페이지는 oldest 이전으로\n    prev = fetch_kline(&apos;BTCUSDT&apos;, interval=&apos;60&apos;, end_ms=oldest - 1)\n    print(f&apos;prev page candles: {len(prev)}&apos;)\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>주의: \u003Ccode>requests.Session\u003C\u002Fcode>은 프록시 URL을 고정하므로, 스티키 세션을 쓸 때는 세션 객체를 재사용해야 합니다. 매 요청마다 새 \u003Ccode>Session()\u003C\u002Fcode>을 만들면 프록시 URL이 바뀌지 않아 의도한 대로 동작하지만, \u003Ccode>sticky_id\u003C\u002Fcode>를 명시적으로 넣는 것이 IP 일관성을 보장합니다.\u003C\u002Fp>\n\u003Ch2>엔드포인트별 속도 예산과 회로 차단기\u003C\u002Fh2>\n\u003Cp>회전 프록시가 IP 분산을 담당하더라도, 애플리케이션 단에서 엔드포인트별로 독립된 속도 예산을 두어야 합니다. 예를 들어 orderbook은 5초당 600회 이하, tickers는 5초당 200회 이하로 제한하고, 403 비율이 임계값(예: 10%)을 넘으면 회로 차단기를 열어 60초간 해당 엔드포인트 호출을 중단합니다.\u003C\u002Fp>\n\u003Cpre>\u003Ccode>\u002F\u002F rate-budget.js\nconst axios = require(&apos;axios&apos;);\nconst { HttpsProxyAgent } = require(&apos;https-proxy-agent&apos;);\n\nclass RateBudget {\n  constructor(windowMs, max) {\n    this.windowMs = windowMs;\n    this.max = max;\n    this.timestamps = [];\n  }\n  allow() {\n    const now = Date.now();\n    this.timestamps = this.timestamps.filter(t =&gt; now - t &lt; this.windowMs);\n    if (this.timestamps.length &gt;= this.max) return false;\n    this.timestamps.push(now);\n    return true;\n  }\n}\n\nclass CircuitBreaker {\n  constructor(threshold = 0.1, cooldownMs = 60000) {\n    this.threshold = threshold;\n    this.cooldownMs = cooldownMs;\n    this.failures = 0;\n    this.total = 0;\n    this.openUntil = 0;\n  }\n  isOpen() { return Date.now() &lt; this.openUntil; }\n  record(ok) {\n    this.total++;\n    if (!ok) this.failures++;\n    if (this.total &gt; 20 &amp;&amp; this.failures \u002F this.total &gt; this.threshold) {\n      this.openUntil = Date.now() + this.cooldownMs;\n      this.failures = 0; this.total = 0;\n    }\n  }\n}\n\nconst orderbookBudget = new RateBudget(5000, 500); \u002F\u002F 여유분\nconst breaker = new CircuitBreaker(0.1, 60000);\n\nasync function guardedOrderbook(symbol) {\n  if (breaker.isOpen()) throw new Error(&apos;circuit open, backing off&apos;);\n  if (!orderbookBudget.allow()) {\n    await new Promise(r =&gt; setTimeout(r, 200));\n    return guardedOrderbook(symbol);\n  }\n  const sid = `${symbol}-${Date.now()}`;\n  const agent = new HttpsProxyAgent(\n    `http:\u002F\u002Fuser-country-DE-sid-${sid}:pass@gate.proxyhat.com:8080`\n  );\n  try {\n    const res = await axios.get(&apos;https:\u002F\u002Fapi.bybit.com\u002Fv5\u002Fmarket\u002Forderbook&apos;, {\n      params: { category: &apos;spot&apos;, symbol, limit: 50 },\n      httpsAgent: agent, timeout: 8000,\n    });\n    breaker.record(res.data.retCode === 0);\n    return res.data.result;\n  } catch (e) {\n    breaker.record(false);\n    throw e;\n  }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2>REST 스냅샷 vs WebSocket orderbook.50\u003C\u002Fh2>\n\u003Cp>REST \u003Ccode>\u002Fv5\u002Fmarket\u002Forderbook\u003C\u002Fcode>은 특정 시점의 스냅샷이며, 폴링 간격이 짧으면 레이트 리밋과 차단 창 위험이 커집니다. 실시간 깊이가 필요하다면 Bybit의 공개 WebSocket 스트림 \u003Ccode>orderbook.50.{symbol}\u003C\u002Fcode> 또는 \u003Ccode>orderbook.200.{symbol}\u003C\u002Fcode>을 구독하는 것이 훨씬 효율적입니다. WebSocket은 단일 연결로 푸시를 받으므로 HTTP 요청당 레이트 리밋을 소비하지 않습니다. 다만 WebSocket 연결 자체도 지역 제한을 받으므로, 제한 지역에서는 프록시가 필요합니다.\u003C\u002Fp>\n\u003Cpre>\u003Ccode># ws_orderbook.py\nimport asyncio, json, websockets\n\nasync def listen_orderbook(symbol=&apos;BTCUSDT&apos;):\n    # SOCKS5 프록시로 WebSocket 연결 (websockets 라이브러리는 socks 지원)\n    proxy = &apos;socks5:\u002F\u002Fuser-country-DE-sid-ws1:pass@gate.proxyhat.com:1080&apos;\n    url = &apos;wss:\u002F\u002Fstream.bybit.com\u002Fv5\u002Fpublic\u002Fspot&apos;\n    async with websockets.connect(url, proxy=proxy, ping_interval=20) as ws:\n        await ws.send(json.dumps({\n            &apos;op&apos;: &apos;subscribe&apos;,\n            &apos;args&apos;: [f&apos;orderbook.50.{symbol}&apos;]\n        }))\n        async for msg in ws:\n            data = json.loads(msg)\n            if data.get(&apos;topic&apos;, &apos;&apos;).startswith(&apos;orderbook.50&apos;):\n                ob = data[&apos;data&apos;]\n                print(f&apos;{symbol} bid0 {ob[&quot;b&quot;][0][0]} ask0 {ob[&quot;a&quot;][0][0]}&apos;)\n\nasyncio.run(listen_orderbook())\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>WebSocket을 쓸 때는 스티키 세션이 권장됩니다. 회전 세션은 연결마다 새 IP를 할당하므로, Bybit가 연결을 끊거나 재인증을 요구할 수 있습니다. \u003Ccode>-sid-ws1\u003C\u002Fcode>처럼 고정 세션을 쓰면 연결 안정성이 올라갑니다.\u003C\u002Fp>\n\u003Ch2>ProxyHat 설정 요약\u003C\u002Fh2>\n\u003Cul>\n\u003Cli>HTTP 기본: \u003Ccode>http:\u002F\u002Fuser-country-DE:pass@gate.proxyhat.com:8080\u003C\u002Fcode>\u003C\u002Fli>\n\u003Cli>SOCKS5: \u003Ccode>socks5:\u002F\u002Fuser-country-DE:pass@gate.proxyhat.com:1080\u003C\u002Fcode>\u003C\u002Fli>\n\u003Cli>도시 타겟: \u003Ccode>user-country-DE-region-state_of_berlin-city-berlin:pass@...\u003C\u002Fcode>\u003C\u002Fli>\n\u003Cli>스티키 세션: \u003Ccode>user-country-DE-sid-abc123:pass@...\u003C\u002Fcode>\u003C\u002Fli>\n\u003Cli>회전(요청마다): 세션 ID를 매 요청마다 새로 생성\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>요금제와 풀 크기는 \u003Ca href=\"\u002Fko\u002Fpricing\">ProxyHat 요금 페이지\u003C\u002Fa>에서 확인하세요. 웹 스크래핑 일반 패턴은 \u003Ca href=\"\u002Fko\u002Fuse-cases\u002Fweb-scraping\">웹 스크래핑 사용 사례\u003C\u002Fa>를, SERP\u002F검색 결과 수집은 \u003Ca href=\"\u002Fko\u002Fuse-cases\u002Fserp-tracking\">SERP 추적 사용 사례\u003C\u002Fa>를 참고하세요.\u003C\u002Fp>\n\u003Ch2>핵심 요약\u003C\u002Fh2>\n\u003Cblockquote>\n\u003Cul>\n\u003Cli>Bybit V5 마켓 데이터는 \u003Ccode>\u002Fv5\u002Fmarket\u002F\u003C\u002Fcode> 아래 4개 엔드포인트, \u003Ccode>category\u003C\u002Fcode>로 자산군 구분, \u003Ccode>retCode\u002FretMsg\u003C\u002Fcode> 봉투 사용.\u003C\u002Fli>\n\u003Cli>IP 기반 레이트 리밋 초과 시 403 + 약 10분 차단 창. 회전 프록시로 IP 분산 필수.\u003C\u002Fli>\n\u003Cli>미국\u002F영국 등 제한 지역은 403\u002F451. \u003Ccode>-country-DE\u003C\u002Fcode> 등 허용 국가 IP로 우회.\u003C\u002Fli>\n\u003Cli>kline 페이지네이션은 스티키 세션(\u003Ccode>-sid-abc123\u003C\u002Fcode>)으로 IP 일관성 유지.\u003C\u002Fli>\n\u003Cli>실시간 깊이는 REST 폴링 대신 WebSocket \u003Ccode>orderbook.50\u003C\u002Fcode> 구독 권장.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003C\u002Fblockquote>","회전 프록시로 암호화폐 시장 데이터 수집 (Bybit V5) | ProxyHat","Bybit V5 Market API의 orderbook, tickers, kline 엔드포인트를 회전 프록시로 안정 스크랩하는 방법. IP 레이트 리밋, 지역 제한, Node.js\u002FPython 예제 포함.","\u002Fko\u002Fblog\u002Fbybit-v5-market-api-proxy-scraping",null,"회전 프록시 암호화폐 시장 데이터 수집 가이드 | ProxyHat","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fko\u002Fbybit-v5-market-api-proxy-scraping-og.webp",[18,21,24],{"question":19,"answer":20},"왜 Bybit API 스크랩에 프록시가 필요한가요?","Bybit는 엔드포인트별 IP 기반 레이트 리밋을 두며, 초과 시 약 10분간 해당 IP를 차단합니다. 또한 미국\u002F영국 등 제한 지역 IP는 403\u002F451을 받습니다. 회전 \u003Ca href=\"\u002Fko\u002Fproxy\u002Fresidential\">레지덴셜 프록시\u003C\u002Fa>는 IP 카운터를 분산시켜 차단 창을 피하고, 허용 국가 IP로 지역 제한을 우회할 수 있게 합니다.",{"question":22,"answer":23},"어떤 프록시 유형이 Bybit 스크랩에 가장 적합한가요?","레지덴셜 프록시가 가장 안전합니다. 데이터센터 IP는 풀이 작아 동일 IP가 반복 사용되어 차단되기 쉽고, 일부 거래소가 데이터센터 ASN을 차단하기도 합니다. 레지덴셜은 수백만 IP 풀로 자연스러운 분산이 가능하며, -country-DE로 지역 제한 우회도 가능합니다.",{"question":25,"answer":26},"Bybit 스크랩 시 차단을 피하려면 어떻게 해야 하나요?","요청마다 새 세션 ID로 IP를 회전하고, 엔드포인트별 독립 속도 예산을 설정하세요. 403 수신 시 지수 백오프 재시도, 회로 차단기로 임계 초과 시 일시 중단, kline 페이지네이션에는 스티키 세션으로 IP 일관성 유지가 핵심입니다. 또한 robots.txt와 Bybit TOS를 준수해야 합니다.",false,"2026-08-03T16:09:16+00:00","2026-10-04T01:29:51+00:00","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fko\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\u002Fko\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,"gaebaljja-gaideu","개발자 가이드","개발자 가이드 | ProxyHat 블로그","프록시를 애플리케이션에 통합하기 위한 코드 튜토리얼 및 SDK 가이드.",[],{"de":47,"fr":48,"it":49,"pt":50,"ru":51,"zh":52,"pl":53,"ko":13,"es":54,"en":55,"ja":56,"x-default":55},"\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","\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","\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":47,"fr":48,"it":49,"pt":50,"ru":51,"zh":52,"pl":53,"ko":13,"es":54,"en":55,"ja":56,"tr":58},"\u002Ftr\u002Fblog\u002Fbybit-v5-market-api-dondurulen-proxy",87,[61,94,121,137],{"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":71,"content_updated_at":72,"reading_time_minutes":73,"is_featured":27,"indexable":4,"views":73,"author":74,"categories":75,"tags":77},210,"ai-agent-proxy-seoljeong","AI 에이전트 프록시 설정: browser-use·Crawl4AI·MCP","클라우드 VM의 에이전트는 데이터센터 IP로 접속합니다. browser-use, Crawl4AI, MCP 서버에서 지금 작동하는 프록시 설정을 sticky와 로테이션 선택 표, 피해야 할 비용 함정과 함께 정리했습니다.","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fko\u002Fai-agent-proxy-seoljeong-master.webp","Proxy Setup for AI Agents: browser-use, Crawl4AI and an MCP Server","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fko\u002Fai-agent-proxy-seoljeong-card.webp","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fko\u002Fai-agent-proxy-seoljeong-og.webp","2026-10-24T09:00:00+00:00","2026-10-24T09:00:20+00:00","2026-10-03T09:41:40+00:00",14,{"name":35,"slug":36,"bio":37,"avatar_url":14,"website_url":14,"social_links":14},[76],{"id":40,"slug":41,"name":42,"description":14,"meta_title":43,"meta_description":44,"parent_id":14},[78,82,86,90],{"id":79,"slug":80,"name":81},1,"web-scraping","웹 스크래핑",{"id":83,"slug":84,"name":85},2,"residential-proxies","주거용 프록시",{"id":87,"slug":88,"name":89},9,"python","Python",{"id":91,"slug":92,"name":93},22,"playwright","Playwright",{"id":95,"slug":96,"title":97,"excerpt":98,"featured_image_url":99,"featured_image_alt":100,"card_image_url":101,"og_image_url":102,"published_at":103,"updated_at":104,"content_updated_at":72,"reading_time_minutes":73,"is_featured":27,"indexable":4,"views":105,"author":106,"categories":107,"tags":109},206,"camoufox-residential-proxy-python-gaideu","Camoufox와 레지덴셜 프록시: 코드로 보는 Python 가이드","C++ 레벨에서 패치한 Firefox인 Camoufox를 레지덴셜 프록시 뒤에서 돌리는 방법. 최신 Python API, geoip에 스티키 세션이 필요한 이유, 핑거프린트 일관성 체크리스트, 그리고 Patchright나 nodriver가 더 맞는 경우를 정리했습니다.","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fko\u002Fcamoufox-residential-proxy-python-gaideu-master.webp","Camoufox with Residential Proxies: A Code-First Python Guide","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fko\u002Fcamoufox-residential-proxy-python-gaideu-card.webp","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fko\u002Fcamoufox-residential-proxy-python-gaideu-og.webp","2026-10-13T09:00:00+00:00","2026-10-13T09:00:22+00:00",30,{"name":35,"slug":36,"bio":37,"avatar_url":14,"website_url":14,"social_links":14},[108],{"id":40,"slug":41,"name":42,"description":14,"meta_title":43,"meta_description":44,"parent_id":14},[110,111,112,116,117],{"id":79,"slug":80,"name":81},{"id":83,"slug":84,"name":85},{"id":113,"slug":114,"name":115},6,"anti-detection","안티 탐지",{"id":87,"slug":88,"name":89},{"id":118,"slug":119,"name":120},21,"headless-browser","헤드리스 브라우저",{"id":122,"slug":123,"title":124,"excerpt":125,"featured_image_url":126,"featured_image_alt":127,"card_image_url":128,"og_image_url":129,"published_at":130,"updated_at":130,"content_updated_at":131,"reading_time_minutes":33,"is_featured":27,"indexable":4,"views":132,"author":133,"categories":134,"tags":136},176,"got-scraping-nodejs-proxy-guide-1","Node.js에서 got-scraping과 주거 프록시로 웹 스크래핑하기","got-scraping의 헤더 생성기와 HTTP\u002F2 지원을 활용해 차단을 우회하는 방법, ProxyHat 주거 프록시 라우팅, 그리고 Crawlee 통합까지 다루는 실전 가이드입니다.","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fko\u002Fgot-scraping-nodejs-proxy-guide-1-master.webp","got-scraping in Node.js: A Developer's Guide with Residential Proxies","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fko\u002Fgot-scraping-nodejs-proxy-guide-1-card.webp","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fko\u002Fgot-scraping-nodejs-proxy-guide-1-og.webp","2026-08-04T16:05:06+00:00","2026-10-03T08:29:58+00:00",121,{"name":35,"slug":36,"bio":37,"avatar_url":14,"website_url":14,"social_links":14},[135],{"id":40,"slug":41,"name":42,"description":14,"meta_title":43,"meta_description":44,"parent_id":14},[],{"id":138,"slug":139,"title":140,"excerpt":141,"featured_image_url":142,"featured_image_alt":143,"card_image_url":144,"og_image_url":145,"published_at":146,"updated_at":146,"content_updated_at":147,"reading_time_minutes":33,"is_featured":27,"indexable":27,"views":148,"author":149,"categories":150,"tags":152},175,"colly-rotating-proxy-guide","Colly에서 로테이션 프록시 사용하기: Go 웹 스크래핑 완전 가이드","Go의 Colly 프레임워크에서 RoundRobinProxySwitcher와 SetProxyFunc를 활용해 ProxyHat 주거 프록시를 로테이션하는 방법을 코드 예제와 함께 다룹니다. 프로덕션 패턴, 재시도, 분산 스크래핑까지.","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fko\u002Fcolly-rotating-proxy-guide-master.webp","Rotating Proxies in Colly: A Framework-Idiomatic Guide for Go Developers","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fko\u002Fcolly-rotating-proxy-guide-card.webp","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fko\u002Fcolly-rotating-proxy-guide-og.webp","2026-08-04T10:05:34+00:00","2026-10-03T23:53:00+00:00",71,{"name":35,"slug":36,"bio":37,"avatar_url":14,"website_url":14,"social_links":14},[151],{"id":40,"slug":41,"name":42,"description":14,"meta_title":43,"meta_description":44,"parent_id":14},[],[]]