[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"blog-post-cn-binance-rest-api-proxy-scraping-guide":3},{"success":4,"payload":5,"related":66,"errors":159},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":9,"og_image_url":16,"faq_json":17,"key_takeaways":14,"allow_index":4,"noindex_google_only":33,"allow_follow":4,"published_at":34,"updated_at":34,"content_updated_at":35,"featured_image_url":36,"featured_image_alt":37,"card_image_url":38,"reading_time_minutes":39,"author":40,"categories":44,"tags":51,"alternates":52,"locale_paths":58,"views":65},194,"binance-rest-api-proxy-scraping-guide","加密货币交易所 API 权重限速：如何通过代理采集市场数据（以 Binance 为例）","面向量化开发者的 Binance REST API 代理抓取指南，涵盖权重限速、IP 轮换、住宅代理配置及生产级代码示例。","\u003Ch2>如何使用代理抓取 Binance REST API：核心思路\u003C\u002Fh2>\n\u003Cp>在量化交易和加密数据工程中，binance api scraping 是构建价格与订单簿数据集的基础工作。Binance 的公开 REST API 提供了 K 线、深度、24 小时行情等端点，但采用了基于权重的 IP 级限速机制：每个 IP 每分钟约有 6000 权重预算，超限会触发 HTTP 429，持续违规会导致 HTTP 418 IP 封禁。通过 \u003Cstrong>住宅代理\u003C\u002Fstrong> 轮换 IP，可以将权重消耗分散到多个出口地址，从而在合规范围内实现大规模数据采集。本文将带你从端点映射、限速机制到生产级代码实现，完整掌握 scrape binance market data 的最佳实践。\u003C\u002Fp>\n\u003Cblockquote>\u003Cp>\u003Cstrong>合规声明：\u003C\u002Fstrong>本文仅涉及 Binance 公开市场数据（public market data）的采集，不涉及账户交易端点或私有数据。请遵守 Binance 服务条款，尊重 API 权重限制，在条款要求官方 API 访问的场景下优先使用官方接口。详情参阅 \u003Ca href=\"https:\u002F\u002Fwww.binance.com\u002Fen\u002Fterms\" rel=\"noopener noreferrer\">Binance 服务条款\u003C\u002Fa>。\u003C\u002Fp>\u003C\u002Fblockquote>\n\n\u003Ch2>Binance 权重限速机制：为什么单 IP 采集会快速耗尽预算\u003C\u002Fh2>\n\u003Cp>Binance 对 REST API 请求采用\u003Cstrong>基于权重的速率限制\u003C\u002Fstrong>（weight-based rate limiting），而非简单的请求次数限制。不同端点消耗不同权重，响应头中的 \u003Ccode>X-MBX-USED-WEIGHT-1M\u003C\u002Fcode> 标头会告诉你当前 IP 在过去 1 分钟内已消耗的权重总量。\u003C\u002Fp>\n\u003Cp>根据 \u003Ca href=\"https:\u002F\u002Fbinance-docs.github.io\u002Fapidocs\u002Fspot\u002Fen\u002F#limits\" rel=\"noopener noreferrer\">Binance 官方 API 文档\u003C\u002Fa>，关键规则如下：\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>每 IP 每分钟权重上限：\u003C\u002Fstrong>约 6000（具体值可能调整，以官方文档为准）\u003C\u002Fli>\n\u003Cli>\u003Cstrong>HTTP 429：\u003C\u002Fstrong>表示已超限，客户端应立即降低请求频率\u003C\u002Fli>\n\u003Cli>HTTP 418：表示 IP 已被自动封禁，封禁时间通过 \u003Ccode>Retry-After\u003C\u002Fcode> 响应头返回，通常为 2 分钟到数天不等\u003C\u002Fli>\n\u003Cli>HTTP 451：因法律原因不可用，通常出现在 Binance.com 对美国地区的地理限制场景\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>问题在于，某些端点的权重消耗非常高。例如 \u003Ccode>\u002Fapi\u002Fv3\u002Fdepth\u003C\u002Fcode>（订单簿）端点在请求 limit=5000 时消耗 50 权重，limit=1000 时消耗 20 权重。如果你每秒轮询一次 limit=5000 的深度数据，仅 120 秒就会消耗 6000 权重——即 2 分钟内耗尽整个 IP 的每分钟预算。这就是为什么 binance rest api rate limit proxy 策略至关重要。\u003C\u002Fp>\n\n\u003Ch2>关键公开市场数据端点映射\u003C\u002Fh2>\n\u003Cp>以下是 Binance 公开 REST API 中最常用的四个市场数据端点，以及它们的权重消耗和典型用途：\u003C\u002Fp>\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>端点\u003C\u002Fth>\n\u003Cth>用途\u003C\u002Fth>\n\u003Cth>典型权重\u003C\u002Fth>\n\u003Cth>说明\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\n\u003Ctr>\n\u003Ctd>\u003Ccode>GET \u002Fapi\u002Fv3\u002Fklines\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>K 线\u002F蜡烛图数据\u003C\u002Ftd>\n\u003Ctd>1-2（基于 limit）\u003C\u002Ftd>\n\u003Ctd>limit ≤ 100 时权重为 1，limit &gt; 500 时权重为 5，limit=1000 时权重为 10\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>GET \u002Fapi\u002Fv3\u002Fdepth\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>订单簿快照\u003C\u002Ftd>\n\u003Ctd>1-50\u003C\u002Ftd>\n\u003Ctd>limit=100 权重 1，limit=1000 权重 20，limit=5000 权重 50\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>GET \u002Fapi\u002Fv3\u002Fticker\u002F24hr\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>24 小时行情统计\u003C\u002Ftd>\n\u003Ctd>1-40\u003C\u002Ftd>\n\u003Ctd>单交易对权重 1，全市场（无 symbol 参数）权重 40\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>GET \u002Fapi\u002Fv3\u002Fticker\u002Fprice\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>最新价格\u003C\u002Ftd>\n\u003Ctd>1-2\u003C\u002Ftd>\n\u003Ctd>单交易对权重 1，全市场权重 2\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\n\u003Cp>每次请求后，务必检查响应头 \u003Ccode>X-MBX-USED-WEIGHT-1M\u003C\u002Fcode> 的值。这是你动态调整请求频率的核心依据——当该值接近 5000 时，就应当降低轮询频率或切换出口 IP。\u003C\u002Fp>\n\n\u003Ch2>代理轮换策略：分散权重消耗\u003C\u002Fh2>\n\u003Cp>核心思路很简单：如果单个 IP 每分钟有 6000 权重预算，那么 N 个 IP 就有 N × 6000 的总预算。通过 \u003Ca href=\"\u002Fcn\u002Fproxy\u002Fresidential\">住宅代理\u003C\u002Fa> 轮换，每个请求可以从不同的住宅 IP 发出，将权重分散到多个地址上。\u003C\u002Fp>\n\u003Cp>对于 Binance.com 与 Binance.US 的地理分割问题，Binance.com 对美国地区返回 HTTP 451。使用 ProxyHat 的 \u003Ccode>-country-US\u003C\u002Fcode> 地理定位可以确保请求从美国 IP 发出，从而访问 Binance.US；反之，使用非美国 IP 则可以正常访问 Binance.com。\u003C\u002Fp>\n\u003Cp>ProxyHat 网关连接参数：\u003C\u002Fp>\n\u003Cul>\n\u003Cli>HTTP 网关： \u003Ccode>gate.proxyhat.com:8080\u003C\u002Fcode>\u003C\u002Fli>\n\u003Cli>SOCKS5 网关： \u003Ccode>gate.proxyhat.com:1080\u003C\u002Fcode>\u003C\u002Fli>\n\u003Cli>用户名格式： \u003Ccode>user-country-DE-region-state_of_berlin-city-berlin\u003C\u002Fcode>（地理定位）、\u003Ccode>user-sid-abc123\u003C\u002Fcode>（粘性会话）\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>更多配置细节请参考 \u003Ca href=\"https:\u002F\u002Fdocs.proxyhat.com\u002F\" rel=\"noopener noreferrer\">ProxyHat 官方文档\u003C\u002Fa>。\u003C\u002Fp>\n\n\u003Ch2>代码实现：Python requests 逐请求轮换 IP\u003C\u002Fh2>\n\u003Cp>以下示例展示如何使用 Python \u003Ccode>requests\u003C\u002Fcode> 库通过 ProxyHat 逐请求轮换住宅 IP 抓取 Binance K 线数据，同时实现权重感知限速和指数退避重试。\u003C\u002Fp>\n\u003Cpre>\u003Ccode>import requests\nimport time\nimport random\nimport logging\nfrom urllib.parse import quote\n\nlogging.basicConfig(level=logging.INFO, format=&apos;%(asctime)s [%(levelname)s] %(message)s&apos;)\nlogger = logging.getLogger(__name__)\n\n# ProxyHat credentials\nPROXYHAT_USER = &quot;your_username&quot;\nPROXYHAT_PASS = &quot;your_password&quot;\nPROXYHAT_GATE = &quot;gate.proxyhat.com&quot;\nPROXYHAT_PORT = 8080\n\nBINANCE_BASE = &quot;https:\u002F\u002Fapi.binance.com&quot;\n\n# Weight tracking\nused_weight = 0\nWEIGHT_SOFT_LIMIT = 5000  # soft threshold before rotating\n\ndef get_proxy_url(country=None, session_id=None):\n    &quot;&quot;&quot;Build ProxyHat proxy URL with optional geo-targeting and sticky session.&quot;&quot;&quot;\n    username = PROXYHAT_USER\n    if country:\n        username += f&quot;-country-{country}&quot;\n    if session_id:\n        username += f&quot;-sid-{session_id}&quot;\n    return f&quot;http:\u002F\u002F{username}:{PROXYHAT_PASS}@{PROXYHAT_GATE}:{PROXYHAT_PORT}&quot;\n\ndef fetch_klines(symbol, interval, limit=500, max_retries=5):\n    &quot;&quot;&quot;Fetch klines with IP rotation, weight-aware throttling, and exponential backoff.&quot;&quot;&quot;\n    global used_weight\n    url = f&quot;{BINANCE_BASE}\u002Fapi\u002Fv3\u002Fklines&quot;\n    params = {&quot;symbol&quot;: symbol, &quot;interval&quot;: interval, &quot;limit&quot;: limit}\n\n    for attempt in range(max_retries):\n        # Rotate IP per request — each request gets a fresh residential IP\n        proxy_url = get_proxy_url()\n        proxies = {&quot;http&quot;: proxy_url, &quot;https&quot;: proxy_url}\n\n        try:\n            resp = requests.get(url, params=params, proxies=proxies, timeout=15)\n\n            # Track weight from response header\n            weight_header = resp.headers.get(&quot;X-MBX-USED-WEIGHT-1M&quot;)\n            if weight_header:\n                used_weight = int(weight_header)\n                logger.info(f&quot;Used weight (1m): {used_weight} | Status: {resp.status_code}&quot;)\n\n            if resp.status_code == 200:\n                return resp.json()\n\n            elif resp.status_code == 429:\n                # Rate limited — back off significantly\n                retry_after = int(resp.headers.get(&quot;Retry-After&quot;, 60))\n                logger.warning(f&quot;429 received. Sleeping {retry_after}s...&quot;)\n                time.sleep(retry_after)\n                continue\n\n            elif resp.status_code == 418:\n                # IP banned — this shouldn&apos;t happen with rotation, but handle it\n                retry_after = int(resp.headers.get(&quot;Retry-After&quot;, 120))\n                logger.error(f&quot;418 IP banned! Sleeping {retry_after}s...&quot;)\n                time.sleep(retry_after)\n                continue\n\n            elif resp.status_code == 451:\n                logger.error(&quot;451 geo-blocked. Try country-US for Binance.US.&quot;)\n                # Switch to US geo-targeting\n                proxy_url = get_proxy_url(country=&quot;US&quot;)\n                proxies = {&quot;http&quot;: proxy_url, &quot;https&quot;: proxy_url}\n                resp = requests.get(url, params=params, proxies=proxies, timeout=15)\n                if resp.status_code == 200:\n                    return resp.json()\n                continue\n\n            else:\n                logger.warning(f&quot;Unexpected status {resp.status_code}: {resp.text[:200]}&quot;)\n\n        except requests.RequestException as e:\n            logger.warning(f&quot;Request error attempt {attempt+1}: {e}&quot;)\n\n        # Exponential backoff with jitter\n        backoff = (2 ** attempt) + random.uniform(0, 1)\n        logger.info(f&quot;Backing off {backoff:.1f}s before retry...&quot;)\n        time.sleep(backoff)\n\n    raise RuntimeError(f&quot;Failed after {max_retries} attempts for {symbol} {interval}&quot;)\n\n# Example: fetch BTCUSDT 1m klines\nif __name__ == &quot;__main__&quot;:\n    data = fetch_klines(&quot;BTCUSDT&quot;, &quot;1m&quot;, limit=500)\n    print(f&quot;Got {len(data)} candles. First: open={data[0][1]}, high={data[0][2]}&quot;)\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>这个示例的关键设计点：每次请求使用新的 ProxyHat 住宅 IP，通过 \u003Ccode>X-MBX-USED-WEIGHT-1M\u003C\u002Fcode> 响应头追踪权重消耗，对 429\u002F418 状态码实施退避策略，对 451 地理限制自动切换到美国出口。\u003C\u002Fp>\n\n\u003Ch2>代码实现：ProxyHat SDK 逐请求轮换（对比写法）\u003C\u002Fh2>\n\u003Cp>以下是使用 ProxyHat SDK 封装的等价实现，简化了代理 URL 构建逻辑，适合需要更高级代理管理的场景。\u003C\u002Fp>\n\u003Cpre>\u003Ccode>import httpx\nimport asyncio\nimport logging\nimport random\nfrom typing import Optional\n\nlogging.basicConfig(level=logging.INFO, format=&apos;%(asctime)s [%(levelname)s] %(message)s&apos;)\nlogger = logging.getLogger(__name__)\n\n# ProxyHat SDK wrapper (simplified — adapt to actual SDK if available)\nclass ProxyHatClient:\n    &quot;&quot;&quot;ProxyHat proxy manager with per-request rotation and sticky sessions.&quot;&quot;&quot;\n\n    def __init__(self, username: str, password: str, \n                 gateway: str = &quot;gate.proxyhat.com&quot;, \n                 http_port: int = 8080,\n                 socks5_port: int = 1080):\n        self.username = username\n        self.password = password\n        self.gateway = gateway\n        self.http_port = http_port\n        self.socks5_port = socks5_port\n\n    def http_proxy(self, country: Optional[str] = None, \n                   session_id: Optional[str] = None) -&gt; str:\n        &quot;&quot;&quot;Build HTTP proxy URL with geo-targeting and\u002For sticky session.&quot;&quot;&quot;\n        user = self.username\n        if country:\n            user += f&quot;-country-{country}&quot;\n        if session_id:\n            user += f&quot;-sid-{session_id}&quot;\n        return f&quot;http:\u002F\u002F{user}:{self.password}@{self.gateway}:{self.http_port}&quot;\n\n    def socks5_proxy(self, country: Optional[str] = None,\n                     session_id: Optional[str] = None) -&gt; str:\n        &quot;&quot;&quot;Build SOCKS5 proxy URL.&quot;&quot;&quot;\n        user = self.username\n        if country:\n            user += f&quot;-country-{country}&quot;\n        if session_id:\n            user += f&quot;-sid-{session_id}&quot;\n        return f&quot;socks5:\u002F\u002F{user}:{self.password}@{self.gateway}:{self.socks5_port}&quot;\n\n\n# Initialize client\nproxyhat = ProxyHatClient(username=&quot;your_username&quot;, password=&quot;your_password&quot;)\n\nBINANCE_BASE = &quot;https:\u002F\u002Fapi.binance.com&quot;\n\nasync def fetch_depth_async(symbol: str, limit: int = 100, \n                            max_retries: int = 5) -&gt; dict:\n    &quot;&quot;&quot;Fetch order book depth with async httpx, IP rotation, and backoff.&quot;&quot;&quot;\n    url = f&quot;{BINANCE_BASE}\u002Fapi\u002Fv3\u002Fdepth&quot;\n    params = {&quot;symbol&quot;: symbol, &quot;limit&quot;: limit}\n\n    async with httpx.AsyncClient(timeout=15.0) as client:\n        for attempt in range(max_retries):\n            # Fresh residential IP per request\n            proxy = proxyhat.http_proxy()\n            \n            try:\n                resp = await client.get(url, params=params, proxy=proxy)\n\n                weight = resp.headers.get(&quot;X-MBX-USED-WEIGHT-1M&quot;)\n                if weight:\n                    logger.info(f&quot;Weight: {weight} | Status: {resp.status_code}&quot;)\n\n                if resp.status_code == 200:\n                    return resp.json()\n\n                elif resp.status_code == 429:\n                    retry_after = int(resp.headers.get(&quot;Retry-After&quot;, 60))\n                    logger.warning(f&quot;429 — sleeping {retry_after}s&quot;)\n                    await asyncio.sleep(retry_after)\n\n                elif resp.status_code == 451:\n                    # Geo-blocked — retry with US exit\n                    proxy = proxyhat.http_proxy(country=&quot;US&quot;)\n                    resp = await client.get(url, params=params, proxy=proxy)\n                    if resp.status_code == 200:\n                        return resp.json()\n\n                else:\n                    logger.warning(f&quot;Status {resp.status_code}: {resp.text[:200]}&quot;)\n\n            except (httpx.ProxyError, httpx.ConnectTimeout, httpx.ReadTimeout) as e:\n                logger.warning(f&quot;Proxy\u002Fnetwork error attempt {attempt+1}: {e}&quot;)\n\n            # Exponential backoff with jitter\n            backoff = (2 ** attempt) + random.uniform(0, 1.5)\n            await asyncio.sleep(backoff)\n\n    raise RuntimeError(f&quot;Depth fetch failed for {symbol}&quot;)\n\n\n# Concurrency-limited batch fetch\nasync def fetch_multiple_symbols(symbols: list, limit: int = 100,\n                                 max_concurrent: int = 10) -&gt; list:\n    &quot;&quot;&quot;Fetch depth for multiple symbols with semaphore-controlled concurrency.&quot;&quot;&quot;\n    semaphore = asyncio.Semaphore(max_concurrent)\n\n    async def bounded_fetch(symbol):\n        async with semaphore:\n            return await fetch_depth_async(symbol, limit=limit)\n\n    results = await asyncio.gather(*[bounded_fetch(s) for s in symbols],\n                                    return_exceptions=True)\n    return list(zip(symbols, results))\n\n\nif __name__ == &quot;__main__&quot;:\n    symbols = [&quot;BTCUSDT&quot;, &quot;ETHUSDT&quot;, &quot;BNBUSDT&quot;, &quot;ADAUSDT&quot;, &quot;XRPUSDT&quot;]\n    results = asyncio.run(fetch_multiple_symbols(symbols, limit=100, max_concurrent=5))\n    for sym, data in results:\n        if isinstance(data, dict):\n            print(f&quot;{sym}: {len(data.get(&apos;bids&apos;, []))} bids, {len(data.get(&apos;asks&apos;, []))} asks&quot;)\n        else:\n            print(f&quot;{sym}: ERROR — {data}&quot;)\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>这个异步版本使用 \u003Ccode>httpx.AsyncClient\u003C\u002Fcode> 配合 \u003Ccode>asyncio.Semaphore\u003C\u002Fcode> 控制并发，适合同时抓取多个交易对的深度数据。每个请求通过 ProxyHat SDK 获取新的住宅 IP，避免单 IP 权重超限。\u003C\u002Fp>\n\n\u003Ch2>粘性会话：K 线历史数据回填\u003C\u002Fh2>\n\u003Cp>当需要分页回填历史 K 线数据时，你可能希望在一段时间内保持同一个出口 IP，以利用该 IP 的权重预算。ProxyHat 的 \u003Ccode>-sid-abc123\u003C\u002Fcode> 参数实现粘性会话——同一 session ID 的请求会路由到同一个住宅 IP。\u003C\u002Fp>\n\u003Cpre>\u003Ccode>import requests\nimport time\nimport logging\n\nlogging.basicConfig(level=logging.INFO)\nlogger = logging.getLogger(__name__)\n\nPROXYHAT_USER = &quot;your_username&quot;\nPROXYHAT_PASS = &quot;your_password&quot;\n\nBINANCE_BASE = &quot;https:\u002F\u002Fapi.binance.com&quot;\n\ndef build_sticky_proxy(session_id: str, country: str = None):\n    &quot;&quot;&quot;Build ProxyHat proxy URL with sticky session for paginated backfills.&quot;&quot;&quot;\n    username = f&quot;{PROXYHAT_USER}-sid-{session_id}&quot;\n    if country:\n        username += f&quot;-country-{country}&quot;\n    return f&quot;http:\u002F\u002F{username}:{PROXYHAT_PASS}@gate.proxyhat.com:8080&quot;\n\ndef backfill_klines(symbol: str, interval: str, \n                    start_time: int, end_time: int,\n                    limit_per_req: int = 1000) -&gt; list:\n    &quot;&quot;&quot;Backfill historical klines using sticky session for weight budget reuse.\n    \n    Uses startTime\u002FendTime pagination. Each request consumes ~10 weight\n    (limit=1000). With 6000\u002Fmin budget, we can do ~600 requests\u002Fmin per IP.\n    &quot;&quot;&quot;\n    session_id = f&quot;backfill-{symbol}-{int(time.time())}&quot;\n    proxy_url = build_sticky_proxy(session_id)\n    proxies = {&quot;http&quot;: proxy_url, &quot;https&quot;: proxy_url}\n\n    all_candles = []\n    current_start = start_time\n    request_count = 0\n\n    while current_start &lt; end_time:\n        url = f&quot;{BINANCE_BASE}\u002Fapi\u002Fv3\u002Fklines&quot;\n        params = {\n            &quot;symbol&quot;: symbol,\n            &quot;interval&quot;: interval,\n            &quot;startTime&quot;: current_start,\n            &quot;endTime&quot;: end_time,\n            &quot;limit&quot;: limit_per_req\n        }\n\n        try:\n            resp = requests.get(url, params=params, proxies=proxies, timeout=20)\n            request_count += 1\n\n            # Monitor weight\n            weight = resp.headers.get(&quot;X-MBX-USED-WEIGHT-1M&quot;)\n            if weight and int(weight) &gt; 5000:\n                logger.info(f&quot;Weight at {weight} — cooling down 10s&quot;)\n                time.sleep(10)\n\n            if resp.status_code == 429:\n                retry_after = int(resp.headers.get(&quot;Retry-After&quot;, 30))\n                logger.warning(f&quot;429 — backing off {retry_after}s&quot;)\n                time.sleep(retry_after)\n                # Rotate to new session IP\n                new_session = f&quot;backfill-{symbol}-{int(time.time())}&quot;\n                proxy_url = build_sticky_proxy(new_session)\n                proxies = {&quot;http&quot;: proxy_url, &quot;https&quot;: proxy_url}\n                continue\n\n            if resp.status_code != 200:\n                logger.error(f&quot;Status {resp.status_code}: {resp.text[:200]}&quot;)\n                time.sleep(5)\n                continue\n\n            candles = resp.json()\n            if not candles:\n                logger.info(&quot;No more data — backfill complete&quot;)\n                break\n\n            all_candles.extend(candles)\n            # Move startTime past the last candle&apos;s close time\n            current_start = candles[-1][6] + 1  # index 6 = close time\n            logger.info(f&quot;Fetched {len(candles)} candles | total: {len(all_candles)} | req #{request_count}&quot;)\n\n            # Respect rate limit — small delay between requests\n            time.sleep(0.2)\n\n        except requests.RequestException as e:\n            logger.error(f&quot;Request error: {e}&quot;)\n            time.sleep(5)\n\n    return all_candles\n\n# Backfill 7 days of BTCUSDT 1m klines\nif __name__ == &quot;__main__&quot;:\n    now_ms = int(time.time() * 1000)\n    seven_days_ago = now_ms - (7 * 24 * 60 * 60 * 1000)\n\n    candles = backfill_klines(&quot;BTCUSDT&quot;, &quot;1m&quot;, seven_days_ago, now_ms, limit_per_req=1000)\n    print(f&quot;Total candles collected: {len(candles)}&quot;)\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>粘性会话的关键优势在于：同一 IP 的权重预算可以被连续的分页请求复用，避免了每请求轮换时的权重浪费。当 \u003Ccode>X-MBX-USED-WEIGHT-1M\u003C\u002Fcode> 接近上限或收到 429 时，切换到新的 session ID 即可获得新的 IP 和新的权重预算。\u003C\u002Fp>\n\n\u003Ch2>Node.js 实现：axios + ProxyHat 代理\u003C\u002Fh2>\n\u003Cp>以下是 Node.js 版本，使用 \u003Ccode>axios\u003C\u002Fcode> 通过 ProxyHat 代理抓取 24 小时行情数据，包含重试和并发控制。\u003C\u002Fp>\n\u003Cpre>\u003Ccode>const axios = require(&apos;axios&apos;);\nconst HttpsProxyAgent = require(&apos;https-proxy-agent&apos;);\n\nconst PROXYHAT_USER = &apos;your_username&apos;;\nconst PROXYHAT_PASS = &apos;your_password&apos;;\nconst PROXYHAT_GATE = &apos;gate.proxyhat.com&apos;;\nconst PROXYHAT_PORT = 8080;\n\nconst BINANCE_BASE = &apos;https:\u002F\u002Fapi.binance.com&apos;;\n\n\u002F**\n * Build ProxyHat proxy URL with optional geo-targeting and sticky session.\n * @param {string|null} country - ISO country code (e.g. &apos;US&apos;, &apos;DE&apos;)\n * @param {string|null} sessionId - Sticky session identifier\n * @returns {string} Full proxy URL\n *\u002F\nfunction buildProxyUrl(country = null, sessionId = null) {\n  let username = PROXYHAT_USER;\n  if (country) username += `-country-${country}`;\n  if (sessionId) username += `-sid-${sessionId}`;\n  return `http:\u002F\u002F${username}:${PROXYHAT_PASS}@${PROXYHAT_GATE}:${PROXYHAT_PORT}`;\n}\n\n\u002F**\n * Fetch 24hr ticker with IP rotation, retries, and weight tracking.\n * @param {string} symbol - Trading pair, e.g. &apos;BTCUSDT&apos;\n * @param {number} maxRetries - Max retry attempts\n * @returns {Promise&lt;object&gt;} Ticker data\n *\u002F\nasync function fetch24hrTicker(symbol, maxRetries = 5) {\n  const url = `${BINANCE_BASE}\u002Fapi\u002Fv3\u002Fticker\u002F24hr`;\n  const params = { symbol };\n\n  for (let attempt = 0; attempt &lt; maxRetries; attempt++) {\n    \u002F\u002F Fresh residential IP per request\n    const proxyUrl = buildProxyUrl();\n    const agent = new HttpsProxyAgent(proxyUrl);\n\n    try {\n      const resp = await axios.get(url, {\n        params,\n        httpsAgent: agent,\n        timeout: 15000,\n        validateStatus: (s) =&gt; s &lt; 500 \u002F\u002F don&apos;t throw on 4xx\n      });\n\n      const weight = resp.headers[&apos;x-mbx-used-weight-1m&apos;];\n      if (weight) {\n        console.log(`[Weight: ${weight}] Status: ${resp.status} | ${symbol}`);\n      }\n\n      if (resp.status === 200) {\n        return resp.data;\n      }\n\n      if (resp.status === 429) {\n        const retryAfter = parseInt(resp.headers[&apos;retry-after&apos;] || &apos;60&apos;, 10);\n        console.warn(`429 — sleeping ${retryAfter}s`);\n        await sleep(retryAfter * 1000);\n        continue;\n      }\n\n      if (resp.status === 418) {\n        const retryAfter = parseInt(resp.headers[&apos;retry-after&apos;] || &apos;120&apos;, 10);\n        console.error(`418 IP banned — sleeping ${retryAfter}s`);\n        await sleep(retryAfter * 1000);\n        continue;\n      }\n\n      if (resp.status === 451) {\n        console.warn(&apos;451 geo-blocked — retrying with US exit&apos;);\n        const usProxy = buildProxyUrl(&apos;US&apos;);\n        const usAgent = new HttpsProxyAgent(usProxy);\n        const usResp = await axios.get(url, { params, httpsAgent: usAgent, timeout: 15000 });\n        if (usResp.status === 200) return usResp.data;\n      }\n\n      console.warn(`Unexpected status ${resp.status}: ${JSON.stringify(resp.data).slice(0, 200)}`);\n\n    } catch (err) {\n      console.warn(`Error attempt ${attempt + 1}: ${err.message}`);\n    }\n\n    \u002F\u002F Exponential backoff with jitter\n    const backoff = Math.pow(2, attempt) * 1000 + Math.random() * 1500;\n    console.log(`Backing off ${(backoff \u002F 1000).toFixed(1)}s...`);\n    await sleep(backoff);\n  }\n\n  throw new Error(`Failed after ${maxRetries} attempts for ${symbol}`);\n}\n\n\u002F**\n * Batch fetch tickers with concurrency limit.\n * @param {string[]} symbols - Array of trading pairs\n * @param {number} concurrency - Max concurrent requests\n * @returns {Promise&lt;Array&gt;} Array of {symbol, data} or {symbol, error}\n *\u002F\nasync function batchFetchTickers(symbols, concurrency = 5) {\n  const results = [];\n  let index = 0;\n\n  async function worker() {\n    while (index &lt; symbols.length) {\n      const i = index++;\n      const sym = symbols[i];\n      try {\n        const data = await fetch24hrTicker(sym);\n        results.push({ symbol: sym, data });\n      } catch (err) {\n        results.push({ symbol: sym, error: err.message });\n      }\n    }\n  }\n\n  \u002F\u002F Launch concurrency-limited workers\n  await Promise.all(Array.from({ length: concurrency }, () =&gt; worker()));\n  return results;\n}\n\nfunction sleep(ms) {\n  return new Promise(resolve =&gt; setTimeout(resolve, ms));\n}\n\n\u002F\u002F Example usage\n(async () =&gt; {\n  const symbols = [&apos;BTCUSDT&apos;, &apos;ETHUSDT&apos;, &apos;BNBUSDT&apos;, &apos;SOLUSDT&apos;, &apos;ADAUSDT&apos;,\n                   &apos;DOGEUSDT&apos;, &apos;XRPUSDT&apos;, &apos;DOTUSDT&apos;, &apos;MATICUSDT&apos;, &apos;LINKUSDT&apos;];\n  const results = await batchFetchTickers(symbols, concurrency = 5);\n\n  for (const r of results) {\n    if (r.data) {\n      console.log(`${r.symbol}: price=${r.data.lastPrice} | vol=${r.data.volume} | change=${r.data.priceChangePercent}%`);\n    } else {\n      console.error(`${r.symbol}: FAILED — ${r.error}`);\n    }\n  }\n})();\n\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Ch2>curl 命令行快速验证\u003C\u002Fh2>\n\u003Cp>在编写代码之前，用 \u003Ccode>curl\u003C\u002Fcode> 快速验证代理连通性和权重消耗：\u003C\u002Fp>\n\u003Cpre>\u003Ccode># Basic klines request through ProxyHat residential proxy\ncurl -x http:\u002F\u002Fyour_username:your_password@gate.proxyhat.com:8080 \\\n  &quot;https:\u002F\u002Fapi.binance.com\u002Fapi\u002Fv3\u002Fklines?symbol=BTCUSDT&amp;interval=1m&amp;limit=100&quot; \\\n  -D -  # dump headers to see X-MBX-USED-WEIGHT-1M\n\n# Depth with limit=1000 (weight=20) through US exit\ncurl -x http:\u002F\u002Fyour_username-country-US:your_password@gate.proxyhat.com:8080 \\\n  &quot;https:\u002F\u002Fapi.binance.com\u002Fapi\u002Fv3\u002Fdepth?symbol=BTCUSDT&amp;limit=1000&quot; \\\n  -D -\n\n# 24hr ticker for single symbol (weight=1)\ncurl -x http:\u002F\u002Fyour_username:your_password@gate.proxyhat.com:8080 \\\n  &quot;https:\u002F\u002Fapi.binance.com\u002Fapi\u002Fv3\u002Fticker\u002F24hr?symbol=ETHUSDT&quot; \\\n  -D -\n\n# Sticky session for paginated backfill\ncurl -x http:\u002F\u002Fyour_username-sid-backfill001:your_password@gate.proxyhat.com:8080 \\\n  &quot;https:\u002F\u002Fapi.binance.com\u002Fapi\u002Fv3\u002Fklines?symbol=BTCUSDT&amp;interval=1m&amp;startTime=1700000000000&amp;limit=1000&quot; \\\n  -D -\n\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Ch2>WebSocket vs REST：何时选择流式数据\u003C\u002Fh2>\n\u003Cp>对于实时市场数据，Binance 提供 \u003Ca href=\"https:\u002F\u002Fbinance-docs.github.io\u002Fapidocs\u002Fspot\u002Fen\u002F#websocket-market-streams\" rel=\"noopener noreferrer\">WebSocket 市场流\u003C\u002Fa>（\u003Ccode>wss:\u002F\u002Fstream.binance.com:9443\u003C\u002Fcode>），包括 \u003Ccode>kline\u003C\u002Fcode>、\u003Ccode>depth\u003C\u002Fcode>、\u003Ccode>trade\u003C\u002Fcode> 等频道。在以下场景中，WebSocket 优于 REST 轮询：\u003C\u002Fp>\n\u003Cul>\n\u003Cli>实时 K 线更新： \u003Ccode>&lt;symbol&gt;@kline_&lt;interval&gt;\u003C\u002Fcode> 频道每 250ms-2000ms 推送一次更新，无需重复请求\u003C\u002Fli>\n\u003Cli>增量深度更新： \u003Ccode>&lt;symbol&gt;@depth\u003C\u002Fcode> 频道推送订单簿增量，避免每秒轮询 \u003Ccode>\u002Fapi\u002Fv3\u002Fdepth\u003C\u002Fcode> 消耗 20-50 权重\u003C\u002Fli>\n\u003Cli>多交易对实时监控： 单个 WebSocket 连接可订阅多个频道，权重消耗为零\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>但 REST 仍然适用于：\u003C\u002Fp>\n\u003Cul>\n\u003Cli>历史数据回填（WebSocket 只提供实时数据）\u003C\u002Fli>\n\u003Cli>一次性快照查询\u003C\u002Fli>\n\u003Cli>需要精确控制请求时机的场景\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>最佳实践是混合使用：用 REST 回填历史数据，用 WebSocket 维护实时更新。两者可以结合代理使用——WebSocket 连接也通过 ProxyHat SOCKS5 代理（\u003Ccode>gate.proxyhat.com:1080\u003C\u002Fcode>）建立。\u003C\u002Fp>\n\n\u003Ch2>常见错误与边界情况\u003C\u002Fh2>\n\u003Ch3>1. 忽略 X-MBX-USED-WEIGHT-1M 响应头\u003C\u002Fh3>\n\u003Cp>很多开发者只检查 HTTP 状态码，不追踪权重消耗。这会导致你在毫无预警的情况下触发 429。正确做法是每次请求后解析该响应头，当值超过 5000 时主动降速或切换 IP。\u003C\u002Fp>\n\u003Ch3>2. 高频轮询 \u002Fapi\u002Fv3\u002Fdepth\u003C\u002Fh3>\n\u003Cp>\u003Ccode>limit=5000\u003C\u002Fcode> 的深度请求消耗 50 权重。如果每 500ms 轮询一次，1 分钟内消耗 6000 权重——直接触顶。解决方案：使用 WebSocket \u003Ccode>@depth\u003C\u002Fcode> 频道，或降低轮询频率并使用多个 IP 分散权重。\u003C\u002Fp>\n\u003Ch3>3. 未处理 HTTP 451 地理限制\u003C\u002Fh3>\n\u003Cp>如果你的出口 IP 位于美国，访问 \u003Ccode>api.binance.com\u003C\u002Fcode> 可能返回 451。使用 \u003Ccode>-country-DE\u003C\u002Fcode> 或其他非美国地理定位可以避免此问题。反之，如需访问 Binance.US，使用 \u003Ccode>-country-US\u003C\u002Fcode>。\u003C\u002Fp>\n\u003Ch3>4. 重试风暴\u003C\u002Fh3>\n\u003Cp>收到 429 后立即重试会加剧限速。务必实现指数退避并尊重 \u003Ccode>Retry-After\u003C\u002Fcode> 头。在 418 封禁场景下，应切换到完全不同的 IP（新的 session ID）。\u003C\u002Fp>\n\u003Ch3>5. 并发不受控\u003C\u002Fh3>\n\u003Cp>无限制并发会导致代理连接池耗尽和目标服务器拒绝连接。使用信号量或连接池限制并发数——对于 Binance API，建议每 IP 不超过 5-10 并发请求。\u003C\u002Fp>\n\n\u003Ch2>生产级最佳实践\u003C\u002Fh2>\n\u003Cul>\n\u003Cli>权重监控： 始终解析 \u003Ccode>X-MBX-USED-WEIGHT-1M\u003C\u002Fcode>，设置软阈值（如 5000）触发 IP 轮换\u003C\u002Fli>\n\u003Cli>请求间隔： 即使使用代理，也保持 200-500ms 的基础间隔，避免突发流量\u003C\u002Fli>\n\u003Cli>断路器模式： 连续 3 次 429\u002F418 后，暂停该 session ID 5 分钟\u003C\u002Fli>\n\u003Cli>日志记录： 记录每个请求的 IP、权重、状态码、延迟，用于事后分析和优化\u003C\u002Fli>\n\u003Cli>数据验证： Binance 返回的 K 线数据是数组格式，索引含义需对照 \u003Ca href=\"https:\u002F\u002Fbinance-docs.github.io\u002Fapidocs\u002Fspot\u002Fen\u002F#kline-candlestick-data\" rel=\"noopener noreferrer\">官方文档\u003C\u002Fa>（索引 0=开盘时间，1=开盘价，6=收盘时间等）\u003C\u002Fli>\n\u003Cli>错误分类： 区分代理错误（网络层）和 API 错误（应用层），分别处理\u003C\u002Fli>\n\u003C\u002Ful>\n\n\u003Ch2>ProxyHat 配置与内部资源\u003C\u002Fh2>\n\u003Cp>要开始使用 ProxyHat 住宅代理抓取 Binance 数据，请按以下步骤配置：\u003C\u002Fp>\n\u003Col>\n\u003Cli>注册并获取 ProxyHat 凭证（用户名\u002F密码）\u003C\u002Fli>\n\u003Cli>选择住宅代理套餐——查看 \u003Ca href=\"\u002Fcn\u002Fpricing\">定价页面\u003C\u002Fa>\u003C\u002Fli>\n\u003Cli>使用 \u003Ccode>gate.proxyhat.com:8080\u003C\u002Fcode>（HTTP）或 \u003Ccode>gate.proxyhat.com:1080\u003C\u002Fcode>（SOCKS5）作为网关\u003C\u002Fli>\n\u003Cli>在用户名中添加地理定位和会话参数\u003C\u002Fli>\n\u003Cli>查阅 \u003Ca href=\"\u002Fcn\u002Flocations\">支持的代理位置\u003C\u002Fa> 了解可用的国家\u002F城市\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Cp>更多使用场景请参考 \u003Ca href=\"\u002Fcn\u002Fuse-cases\u002Fweb-scraping\">网络爬虫用例\u003C\u002Fa> 和 \u003Ca href=\"\u002Fcn\u002Fuse-cases\u002Fserp-tracking\">SERP 追踪用例\u003C\u002Fa>。完整 API 文档请访问 \u003Ca href=\"https:\u002F\u002Fdocs.proxyhat.com\u002F\" rel=\"noopener noreferrer\">ProxyHat 文档站\u003C\u002Fa>。\u003C\u002Fp>\n\n\u003Ch2>关键要点总结\u003C\u002Fh2>\n\u003Cblockquote>\n\u003Cul>\n\u003Cli>Binance REST API 采用权重限速，每 IP 每分钟约 6000 权重；高权重端点（如 depth limit=5000 消耗 50 权重）可在 2 分钟内耗尽预算\u003C\u002Fli>\n\u003Cli>通过 ProxyHat 住宅代理轮换 IP，将权重分散到多个出口地址，实现合规的大规模数据采集\u003C\u002Fli>\n\u003Cli>始终解析 \u003Ccode>X-MBX-USED-WEIGHT-1M\u003C\u002Fcode> 响应头，设置软阈值主动降速\u003C\u002Fli>\n\u003Cli>粘性会话（\u003Ccode>-sid-xxx\u003C\u002Fcode>）适合分页回填，逐请求轮换适合高并发抓取\u003C\u002Fli>\n\u003Cli>实时数据优先使用 WebSocket 流，历史数据回填使用 REST + 代理轮换\u003C\u002Fli>\n\u003Cli>对 429\u002F418\u002F451 状态码实施差异化处理策略，避免重试风暴\u003C\u002Fli>\n\u003C\u002Ful>\n\u003C\u002Fblockquote>\n\n\u003Ch2>常见问题\u003C\u002Fh2>\n\u003Ch3>使用代理抓取 Binance REST API 是什么意思？\u003C\u002Fh3>\n\u003Cp>指通过 HTTP\u002FSOCKS5 代理服务器向 Binance 公开 REST API（如 \u002Fapi\u002Fv3\u002Fklines、\u002Fapi\u002Fv3\u002Fdepth 等端点）发送请求，以轮换出口 IP 地址的方式分散 Binance 的权重限速。Binance 对每个 IP 每分钟限制约 6000 权重，超限返回 429，持续违规返回 418 封禁。使用住宅代理可以让每个请求从不同 IP 发出，从而将权重预算乘以 IP 数量，实现规模化采集。\u003C\u002Fp>\n\n\u003Ch3>为什么代理用户需要关注 Binance REST API 抓取？\u003C\u002Fh3>\n\u003Cp>Binance 的权重限速是按 IP 计算的，单 IP 采集深度数据（limit=5000，权重 50）在 2 分钟内就会触顶。代理用户通过轮换住宅 IP 可以将权重分散到多个地址，避免 429\u002F418 封禁，同时通过地理定位（如 -country-US）绕过 Binance.com 对美国地区的 451 限制。这使得大规模历史数据回填和实时多交易对监控成为可能。\u003C\u002Fp>\n\n\u003Ch3>哪种代理类型最适合 Binance REST API 抓取？\u003C\u002Fh3>\n\u003Cp>住宅代理是最佳选择。Binance 的反爬系统对数据中心 IP 更敏感，容易触发更严格的限速或封禁。住宅代理使用真实 ISP 分配的 IP 地址，看起来像普通用户流量，更不容易被标记。ProxyHat 住宅代理通过 gate.proxyhat.com:8080（HTTP）或 :1080（SOCKS5）提供，支持国家\u002F城市级地理定位和粘性会话，适合 Binance 的权重限速场景。\u003C\u002Fp>\n\n\u003Ch3>如何避免 Binance REST API 抓取时的 IP 封禁？\u003C\u002Fh3>\n\u003Cp>关键策略包括：始终监控 X-MBX-USED-WEIGHT-1M 响应头，在达到 5000 时切换 IP；对 429 响应立即降速并尊重 Retry-After 头；使用住宅代理逐请求轮换 IP；避免高频轮询高权重端点（如 depth limit=5000）；实现指数退避重试而非立即重试；对 418 封禁切换到全新的 session ID 和 IP。混合使用 WebSocket（实时数据，零权重消耗）和 REST（历史回填）可以进一步降低封禁风险。\u003C\u002Fp>\n\n\u003Ch3>Binance WebSocket 和 REST API 哪个更适合数据采集？\u003C\u002Fh3>\n\u003Cp>取决于场景。WebSocket 适合实时数据——kline、depth、trade 频道推送更新不消耗 REST 权重，单连接可订阅多个频道。REST 适合历史数据回填和一次性快照查询。最佳实践是混合使用：REST + 代理轮填回填历史数据，WebSocket 维护实时更新。WebSocket 连接也可通过 ProxyHat SOCKS5 代理（gate.proxyhat.com:1080）建立。\u003C\u002Fp>\n\u003C\u002Fblockquote>","交易所 API 权重限速与代理数据采集（Binance 示例） | ProxyHat","开发者指南：通过住宅代理抓取 Binance REST API 公开市场数据，涵盖权重限速、IP 轮换、K 线\u002F深度端点及生产级代码示例。","\u002Fcn\u002Fblog\u002Fbinance-rest-api-proxy-scraping-guide",null,"加密货币交易所 API 权重限速指南 | ProxyHat","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fzh\u002Fbinance-rest-api-proxy-scraping-guide-og.webp",[18,21,24,27,30],{"question":19,"answer":20},"使用代理抓取 Binance REST API 是什么意思？","指通过 HTTP\u002FSOCKS5 代理服务器向 Binance 公开 REST API（如 \u002Fapi\u002Fv3\u002Fklines、\u002Fapi\u002Fv3\u002Fdepth 等端点）发送请求，以轮换出口 IP 地址的方式分散 Binance 的权重限速。Binance 对每个 IP 每分钟限制约 6000 权重，超限返回 429，持续违规返回 418 封禁。使用住宅代理可以让每个请求从不同 IP 发出，从而将权重预算乘以 IP 数量，实现规模化采集。",{"question":22,"answer":23},"为什么代理用户需要关注 Binance REST API 抓取？","Binance 的权重限速是按 IP 计算的，单 IP 采集深度数据（limit=5000，权重 50）在 2 分钟内就会触顶。代理用户通过轮换住宅 IP 可以将权重分散到多个地址，避免 429\u002F418 封禁，同时通过地理定位（如 -country-US）绕过 Binance.com 对美国地区的 451 限制。这使得大规模历史数据回填和实时多交易对监控成为可能。",{"question":25,"answer":26},"哪种代理类型最适合 Binance REST API 抓取？","住宅代理是最佳选择。Binance 的反爬系统对数据中心 IP 更敏感，容易触发更严格的限速或封禁。住宅代理使用真实 ISP 分配的 IP 地址，看起来像普通用户流量，更不容易被标记。ProxyHat 住宅代理通过 gate.proxyhat.com:8080（HTTP）或 :1080（SOCKS5）提供，支持国家\u002F城市级地理定位和粘性会话。",{"question":28,"answer":29},"如何避免 Binance REST API 抓取时的 IP 封禁？","关键策略包括：始终监控 X-MBX-USED-WEIGHT-1M 响应头，在达到 5000 时切换 IP；对 429 响应立即降速并尊重 Retry-After 头；使用住宅代理逐请求轮换 IP；避免高频轮询高权重端点；实现指数退避重试而非立即重试；对 418 封禁切换到全新的 session ID 和 IP。混合使用 WebSocket 和 REST 可以进一步降低封禁风险。",{"question":31,"answer":32},"Binance WebSocket 和 REST API 哪个更适合数据采集？","取决于场景。WebSocket 适合实时数据——kline、depth、trade 频道推送更新不消耗 REST 权重，单连接可订阅多个频道。REST 适合历史数据回填和一次性快照查询。最佳实践是混合使用：REST + 代理轮换回填历史数据，WebSocket 维护实时更新。WebSocket 连接也可通过 ProxyHat SOCKS5 代理建立。",false,"2026-08-03T10:04:04+00:00","2026-10-04T01:29:51+00:00","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fzh\u002Fbinance-rest-api-proxy-scraping-guide-master.webp","How to Scrape the Binance REST API with Proxies: A Developer Guide","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fzh\u002Fbinance-rest-api-proxy-scraping-guide-card.webp",12,{"name":41,"slug":42,"bio":43,"avatar_url":14,"website_url":14,"social_links":14},"ProxyHat Team","proxyhat-team","The ProxyHat editorial team covers proxies, web scraping, and data extraction.",[45],{"id":46,"slug":47,"name":48,"description":14,"meta_title":49,"meta_description":50,"parent_id":14},4,"kaifa-zhinan","开发者指南","开发者指南 | ProxyHat 博客","代码教程和SDK指南，帮助您将代理集成到应用程序中。",[],{"fr":53,"ko":54,"ru":55,"zh":13,"pt":56,"en":57,"x-default":57},"\u002Ffr\u002Fblog\u002Fcomment-scraper-api-rest-binance-proxies","\u002Fko\u002Fblog\u002Fbinance-rest-api-proxy-scraping","\u002Fru\u002Fblog\u002Fkak-skrejpit-binance-rest-api-proksi","\u002Fpt\u002Fblog\u002Fcomo-raspar-api-binance-proxies","\u002Fblog\u002Fscrape-binance-rest-api-proxies",{"tr":59,"fr":53,"ja":60,"ko":54,"pl":61,"es":62,"ru":55,"zh":13,"pt":56,"en":57,"it":63,"de":64},"\u002Ftr\u002Fblog\u002Fbinance-rest-api-proxy-tarama","\u002Fja\u002Fblog\u002Fbinance-api-scraping-proxy","\u002Fpl\u002Fblog\u002Fjak-scrapowac-rest-api-binance-proxy","\u002Fes\u002Fblog\u002Fscrapear-api-binance-proxies","\u002Fit\u002Fblog\u002Fscraping-binance-rest-api-con-proxy","\u002Fde\u002Fblog\u002Fbinance-rest-api-mit-proxies-scrapen",81,[67,100,127,143],{"id":68,"slug":69,"title":70,"excerpt":71,"featured_image_url":72,"featured_image_alt":73,"card_image_url":74,"og_image_url":75,"published_at":76,"updated_at":77,"content_updated_at":78,"reading_time_minutes":79,"is_featured":33,"indexable":4,"views":79,"author":80,"categories":81,"tags":83},210,"ai-agent-daili-peizhi","AI Agent 代理配置：browser-use、Crawl4AI、MCP","运行在云服务器上的智能体从数据中心 IP 出口。本文给出 browser-use、Crawl4AI 和 MCP 服务器当前可用的代理配置，附粘性与轮换的决策表，以及需要避开的成本陷阱。","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fzh\u002Fai-agent-daili-peizhi-master.webp","Proxy Setup for AI Agents: browser-use, Crawl4AI and an MCP Server","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fzh\u002Fai-agent-daili-peizhi-card.webp","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fzh\u002Fai-agent-daili-peizhi-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":41,"slug":42,"bio":43,"avatar_url":14,"website_url":14,"social_links":14},[82],{"id":46,"slug":47,"name":48,"description":14,"meta_title":49,"meta_description":50,"parent_id":14},[84,88,92,96],{"id":85,"slug":86,"name":87},1,"web-scraping","网页抓取",{"id":89,"slug":90,"name":91},2,"residential-proxies","住宅代理",{"id":93,"slug":94,"name":95},9,"python","Python",{"id":97,"slug":98,"name":99},22,"playwright","Playwright",{"id":101,"slug":102,"title":103,"excerpt":104,"featured_image_url":105,"featured_image_alt":106,"card_image_url":107,"og_image_url":108,"published_at":109,"updated_at":110,"content_updated_at":78,"reading_time_minutes":79,"is_featured":33,"indexable":4,"views":111,"author":112,"categories":113,"tags":115},206,"camoufox-zhuzhai-daili-python-zhinan","Camoufox 搭配住宅代理：代码优先的 Python 指南","如何让在 C++ 层打补丁的 Firefox——Camoufox 在住宅代理后运行：当前的 Python API、geoip 为什么需要粘性会话、指纹一致性检查清单，以及何时 Patchright 或 nodriver 更合适。","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fzh\u002Fcamoufox-zhuzhai-daili-python-zhinan-master.webp","Camoufox with Residential Proxies: A Code-First Python Guide","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fzh\u002Fcamoufox-zhuzhai-daili-python-zhinan-card.webp","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fzh\u002Fcamoufox-zhuzhai-daili-python-zhinan-og.webp","2026-10-13T09:00:00+00:00","2026-10-13T09:00:22+00:00",29,{"name":41,"slug":42,"bio":43,"avatar_url":14,"website_url":14,"social_links":14},[114],{"id":46,"slug":47,"name":48,"description":14,"meta_title":49,"meta_description":50,"parent_id":14},[116,117,118,122,123],{"id":85,"slug":86,"name":87},{"id":89,"slug":90,"name":91},{"id":119,"slug":120,"name":121},6,"anti-detection","反检测",{"id":93,"slug":94,"name":95},{"id":124,"slug":125,"name":126},21,"headless-browser","无头浏览器",{"id":128,"slug":129,"title":130,"excerpt":131,"featured_image_url":132,"featured_image_alt":133,"card_image_url":134,"og_image_url":135,"published_at":136,"updated_at":136,"content_updated_at":137,"reading_time_minutes":39,"is_featured":33,"indexable":4,"views":138,"author":139,"categories":140,"tags":142},176,"got-scraping-nodejs-proxy-guide","Node.js 中的 got-scraping 完整指南：头部生成与住宅代理实战","深入解析 Apify 的 got-scraping 库——从 header-generator 生成连贯浏览器头部、HTTP\u002F2 支持，到通过 ProxyHat 住宅代理实现大规模 Node.js 爬虫。包含可运行代码、重试钩子、并发控制与生产模式最佳实践。","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fzh\u002Fgot-scraping-nodejs-proxy-guide-master.webp","got-scraping in Node.js: A Developer's Guide with Residential Proxies","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fzh\u002Fgot-scraping-nodejs-proxy-guide-card.webp","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fzh\u002Fgot-scraping-nodejs-proxy-guide-og.webp","2026-08-04T16:05:06+00:00","2026-10-03T08:29:58+00:00",121,{"name":41,"slug":42,"bio":43,"avatar_url":14,"website_url":14,"social_links":14},[141],{"id":46,"slug":47,"name":48,"description":14,"meta_title":49,"meta_description":50,"parent_id":14},[],{"id":144,"slug":145,"title":146,"excerpt":147,"featured_image_url":148,"featured_image_alt":149,"card_image_url":150,"og_image_url":151,"published_at":152,"updated_at":152,"content_updated_at":153,"reading_time_minutes":39,"is_featured":33,"indexable":33,"views":154,"author":155,"categories":156,"tags":158},175,"colly-lunhuan-daili-shixian-zhinan","Colly轮换代理完整指南：用Go构建高吞吐爬虫的实战方案","深入讲解如何在Go的Colly框架中实现代理轮换，涵盖RoundRobinProxySwitcher、SetProxyFunc自定义函数、住宅代理地理定位与会话保持、生产级重试与并发控制，以及分布式存储后端等核心模式。","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fzh\u002Fcolly-lunhuan-daili-shixian-zhinan-master.webp","Rotating Proxies in Colly: A Framework-Idiomatic Guide for Go Developers","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fzh\u002Fcolly-lunhuan-daili-shixian-zhinan-card.webp","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fzh\u002Fcolly-lunhuan-daili-shixian-zhinan-og.webp","2026-08-04T10:05:34+00:00","2026-10-03T08:29:56+00:00",71,{"name":41,"slug":42,"bio":43,"avatar_url":14,"website_url":14,"social_links":14},[157],{"id":46,"slug":47,"name":48,"description":14,"meta_title":49,"meta_description":50,"parent_id":14},[],[]]