[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"blog-post-ru-kak-skrejpit-binance-rest-api-proksi":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":12,"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,"kak-skrejpit-binance-rest-api-proksi","Весовые лимиты API криптобирж: сбор рыночных данных через прокси (на примере Binance)","Практическое руководство по сбору публичных рыночных данных Binance REST API через вращающиеся резидентные прокси: эндпоинты, весовые лимиты, ротация IP, код на Python и Node.js.","\u003Ch2>Как скрейпить Binance REST API через прокси: быстрый ответ\u003C\u002Fh2>\n\u003Cp>Чтобы скрейпить Binance REST API через прокси, нужно направлять запросы к публичным эндпоинтам \u003Ccode>api.binance.com\u003C\u002Fcode> через вращающиеся резидентные прокси \u003Ccode>gate.proxyhat.com:8080\u003C\u002Fcode>, распределяя весовые лимиты по нескольким IP-адресам. Binance использует весовую систему ограничения скорости — около 6000 единиц веса в минуту на IP. Ротация IP через прокси позволяет собирать данные свечей (klines), книги ордеров (depth) и тикеров в масштабе, недоступном с одного адреса.\u003C\u002Fp>\n\u003Cblockquote>\u003Cp>\u003Cstrong>Дисклеймер:\u003C\u002Fstrong> Данная статья охватывает только \u003Cem>публичные рыночные данные\u003C\u002Fem> Binance (эндпоинты \u003Ccode>\u002Fapi\u002Fv3\u002F\u003C\u002Fcode> без аутентификации). Уважайте \u003Ca href=\"https:\u002F\u002Fwww.binance.com\u002Fen\u002Fterms\" rel=\"noopener noreferrer\">Условия использования Binance\u003C\u002Fa> и весовые лимиты API. Если ваши задачи требуют официального доступа, используйте \u003Ca href=\"https:\u002F\u002Fdevelopers.binance.com\u002Fdocs\" rel=\"noopener noreferrer\">официальную документацию Binance API\u003C\u002Fa> и при необходимости запрашивайте повышенные лимиты через поддержку.\u003C\u002Fp>\u003C\u002Fblockquote>\n\n\u003Ch2>Технический контекст: эндпоинты, веса и лимиты\u003C\u002Fh2>\n\u003Cp>Binance REST API для спот-торговли работает на домене \u003Ccode>api.binance.com\u003C\u002Fcode> и предоставляет публичные эндпоинты рыночных данных без аутентификации. Каждый запрос имеет \u003Cstrong>вес\u003C\u002Fstrong> — единицу нагрузки, которая вычитается из минутного бюджета IP-адреса. Заголовок ответа \u003Ccode>X-MBX-USED-WEIGHT-1M\u003C\u002Fcode> показывает текущий израсходованный вес за последнюю минуту.\u003C\u002Fp>\n\n\u003Ch3>Ключевые эндпоинты публичных рыночных данных\u003C\u002Fh3>\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\u003Cth>Эндпоинт\u003C\u002Fth>\u003Cth>Назначение\u003C\u002Fth>\u003Cth>Вес (зависит от параметров)\u003C\u002Fth>\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\n\u003Ctr>\u003Ctd>\u003Ccode>\u002Fapi\u002Fv3\u002Fklines\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>Свечи (OHLCV) по интервалам\u003C\u002Ftd>\u003Ctd>1 (limit ≤ 100), 2 (limit &gt; 100)\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>\u003Ccode>\u002Fapi\u002Fv3\u002Fdepth\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>Книга ордеров (bid\u002Fask)\u003C\u002Ftd>\u003Ctd>1–20 (зависит от limit)\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>\u003Ccode>\u002Fapi\u002Fv3\u002Fticker\u002F24hr\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>24-часовая статистика\u003C\u002Ftd>\u003Ctd>1 (1 символ), 80 (все)\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>\u003Ccode>\u002Fapi\u002Fv3\u002Fticker\u002Fprice\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>Текущая цена\u003C\u002Ftd>\u003Ctd>1 (1 символ), 2 (все)\u003C\u002Ftd>\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\n\n\u003Ch3>Весовая система лимитов и блокировки\u003C\u002Fh3>\n\u003Cp>Binance применяет \u003Cstrong>весовое ограничение скорости\u003C\u002Fstrong> — примерно 6000 единиц веса в минуту на IP-адрес для спот-API. Превышение приводит к следующим ответам:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>HTTP 429\u003C\u002Fstrong> — превышен лимит скорости. Запросы нужно приостановить. Заголовок \u003Ccode>Retry-After\u003C\u002Fcode> указывает время ожидания в секундах.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>HTTP 418\u003C\u002Fstrong> — IP автоматически заблокирован после многократных нарушений 429. Бан длится от 2 минут до нескольких дней.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>HTTP 451\u003C\u002Fstrong> — регион недоступен (географическое ограничение, актуально для Binance.com в США).\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>Тесный поллинг \u003Ccode>\u002Fapi\u002Fv3\u002Fdepth\u003C\u002Fcode> с \u003Ccode>limit=1000\u003C\u002Fcode> (вес 5) исчерпает бюджет 6000 за ~1200 запросов — примерно 20 запросов в секунду исчерпают лимит за 5 минут. С \u003Ccode>limit=5000\u003C\u002Fcode> (вес 20) бюджет уйдёт за 300 запросов — менее чем за 2 минуты при 3 запросах\u002Fсек. Подробнее см. в \u003Ca href=\"https:\u002F\u002Fbinance-docs.github.io\u002Fapidocs\u002Fspot\u002Fen\u002F\" rel=\"noopener noreferrer\">официальной документации Binance Spot API\u003C\u002Fa> и \u003Ca href=\"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FHTTP\u002FReference\u002FStatus\u002F429\" rel=\"noopener noreferrer\">MDN: HTTP 429 Too Many Requests\u003C\u002Fa>.\u003C\u002Fp>\n\n\u003Ch2>Почему прокси необходимы для скрейпинга Binance\u003C\u002Fh2>\n\u003Cp>С одного IP-адреса вы упрётесь в лимит 6000 веса\u002Fмин. Для quant-разработчиков и инженеров криптоданных, собирающих исторические свечи по десяткам торговых пар или поллинг книги ордеров с высокой частотой, этого недостаточно. Вращающиеся \u003Ca href=\"\u002Fru\u002Fproxy\u002Fresidential\">резидентные прокси\u003C\u002Fa> \u003Cstrong>распределяют вес\u003C\u002Fstrong> по пулу IP-адресов — каждый IP получает свой бюджет 6000\u002Fмин.\u003C\u002Fp>\n\u003Cp>Дополнительно, Binance разделяет \u003Ccode>binance.com\u003C\u002Fcode> (глобальный) и \u003Ccode>binance.us\u003C\u002Fcode> (США). Запросы к глобальному API из США могут получить HTTP 451. Геотаргетинг ProxyHat через параметр \u003Ccode>-country-US\u003C\u002Fcode> в имени пользователя позволяет направлять запросы через IP нужной страны.\u003C\u002Fp>\n\n\u003Ch2>Практическая реализация: код и примеры\u003C\u002Fh2>\n\n\u003Ch3>1. Базовый запрос через ProxyHat (curl, HTTP)\u003C\u002Fh3>\n\u003Cp>Простейший способ — направить запрос через HTTP-прокси ProxyHat с геотаргетингом на США:\u003C\u002Fp>\n\u003Cpre>\u003Ccode># Получение свечей BTCUSDT через прокси с IP в США\ncurl -x &quot;http:\u002F\u002Fuser-country-US:pass@gate.proxyhat.com:8080&quot; \\\n  &quot;https:\u002F\u002Fapi.binance.com\u002Fapi\u002Fv3\u002Fklines?symbol=BTCUSDT&amp;interval=1m&amp;limit=100&quot;\n\n# Проверка израсходованного веса\ncurl -s -o \u002Fdev\u002Fnull -D - -x &quot;http:\u002F\u002Fuser-country-US:pass@gate.proxyhat.com:8080&quot; \\\n  &quot;https:\u002F\u002Fapi.binance.com\u002Fapi\u002Fv3\u002Fticker\u002Fprice?symbol=BTCUSDT&quot; \\\n  | grep -i &quot;x-mbx-used-weight-1m&quot;\n\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Ch3>2. Python requests: ротация IP через ProxyHat SDK-паттерн\u003C\u002Fh3>\n\u003Cp>Инкапсулируем логику ProxyHat в класс-обёртку (SDK-паттерн) с отслеживанием веса, retry с экспоненциальной задержкой и автоматической ротацией IP:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>import requests\nimport time\nimport logging\nfrom urllib.parse import urlencode\n\nlogging.basicConfig(level=logging.INFO, format=&quot;%(asctime)s %(levelname)s %(message)s&quot;)\nlogger = logging.getLogger(&quot;binance_scraper&quot;)\n\nclass ProxyHatBinanceClient:\n    &quot;&quot;&quot;SDK-обёртка для скрейпинга Binance через ротацию IP ProxyHat.&quot;&quot;&quot;\n\n    BASE_URL = &quot;https:\u002F\u002Fapi.binance.com&quot;\n    GATE = &quot;gate.proxyhat.com:8080&quot;\n    MAX_WEIGHT_PER_MIN = 5500  # буфер 500 ниже лимита 6000\n\n    def __init__(self, username: str, password: str, country: str = None):\n        self.username = username\n        self.password = password\n        self.country = country\n        self.used_weight = 0\n        self.session = requests.Session()\n\n    def _proxy_url(self, session_id: str = None) -&gt; str:\n        &quot;&quot;&quot;Формирует URL прокси с опциональной гео-привязкой и сессией.&quot;&quot;&quot;\n        user = self.username\n        if self.country:\n            user += f&quot;-country-{self.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.GATE}&quot;\n\n    def _request(self, path: str, params: dict = None, session_id: str = None) -&gt; dict:\n        &quot;&quot;&quot;Выполняет запрос с retry, отслеживанием веса и ротацией IP.&quot;&quot;&quot;\n        url = f&quot;{self.BASE_URL}{path}&quot;\n        proxies = {&quot;http&quot;: self._proxy_url(session_id), &quot;https&quot;: self._proxy_url(session_id)}\n\n        for attempt in range(5):\n            # Throttle: если вес близок к лимиту — ждём\n            if self.used_weight &gt;= self.MAX_WEIGHT_PER_MIN:\n                logger.info(&quot;Weight limit reached (%d), cooling down 60s&quot;, self.used_weight)\n                time.sleep(60)\n                self.used_weight = 0\n\n            try:\n                resp = self.session.get(url, params=params, proxies=proxies, timeout=15)\n                # Обновляем отслеживание веса\n                weight_header = resp.headers.get(&quot;X-MBX-USED-WEIGHT-1M&quot;)\n                if weight_header:\n                    self.used_weight = int(weight_header)\n                    logger.debug(&quot;Used weight: %s&quot;, weight_header)\n\n                if resp.status_code == 429:\n                    retry_after = int(resp.headers.get(&quot;Retry-After&quot;, 10))\n                    logger.warning(&quot;429 rate limited, waiting %ds&quot;, retry_after)\n                    time.sleep(retry_after)\n                    continue\n\n                if resp.status_code == 418:\n                    logger.error(&quot;418 IP banned! Waiting 120s before retry&quot;)\n                    time.sleep(120)\n                    continue\n\n                resp.raise_for_status()\n                return resp.json()\n\n            except requests.RequestException as e:\n                wait = 2 ** attempt\n                logger.warning(&quot;Attempt %d failed: %s, retrying in %ds&quot;, attempt + 1, e, wait)\n                time.sleep(wait)\n\n        raise RuntimeError(f&quot;Failed after 5 attempts: {path}&quot;)\n\n    def get_klines(self, symbol: str, interval: str = &quot;1m&quot;, limit: int = 100) -&gt; list:\n        return self._request(&quot;\u002Fapi\u002Fv3\u002Fklines&quot;, {\n            &quot;symbol&quot;: symbol, &quot;interval&quot;: interval, &quot;limit&quot;: limit\n        })\n\n    def get_depth(self, symbol: str, limit: int = 100) -&gt; dict:\n        return self._request(&quot;\u002Fapi\u002Fv3\u002Fdepth&quot;, {\n            &quot;symbol&quot;: symbol, &quot;limit&quot;: limit\n        })\n\n    def get_ticker_24hr(self, symbol: str = None) -&gt; dict | list:\n        params = {&quot;symbol&quot;: symbol} if symbol else {}\n        return self._request(&quot;\u002Fapi\u002Fv3\u002Fticker\u002F24hr&quot;, params or None)\n\n    def get_price(self, symbol: str = None) -&gt; dict | list:\n        params = {&quot;symbol&quot;: symbol} if symbol else {}\n        return self._request(&quot;\u002Fapi\u002Fv3\u002Fticker\u002Fprice&quot;, params or None)\n\n\n# Использование\nclient = ProxyHatBinanceClient(username=&quot;user&quot;, password=&quot;pass&quot;, country=&quot;US&quot;)\n\n# Ротация IP — каждый запрос идёт через новый IP\nfor sym in [&quot;BTCUSDT&quot;, &quot;ETHUSDT&quot;, &quot;BNBUSDT&quot;]:\n    klines = client.get_klines(sym, interval=&quot;5m&quot;, limit=100)\n    logger.info(&quot;%s: got %d candles&quot;, sym, len(klines))\n\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Ch3>3. Python httpx: асинхронная ротация с контролем параллелизма\u003C\u002Fh3>\n\u003Cp>Для высокопроизводительного сбора данных используйте \u003Ccode>httpx\u003C\u002Fcode> с \u003Ccode>asyncio\u003C\u002Fcode> и семафором для ограничения параллелизма:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>import httpx\nimport asyncio\nimport logging\n\nlogging.basicConfig(level=logging.INFO, format=&quot;%(asctime)s %(levelname)s %(message)s&quot;)\nlogger = logging.getLogger(&quot;async_binance&quot;)\n\nGATE = &quot;gate.proxyhat.com:8080&quot;\nBASE = &quot;https:\u002F\u002Fapi.binance.com&quot;\nMAX_CONCURRENT = 10\n\nasync def fetch_klines(client: httpx.AsyncClient, symbol: str, interval: str, limit: int):\n    &quot;&quot;&quot;Получение klines через асинхронный клиент с прокси.&quot;&quot;&quot;\n    params = {&quot;symbol&quot;: symbol, &quot;interval&quot;: interval, &quot;limit&quot;: limit}\n    try:\n        resp = await client.get(f&quot;{BASE}\u002Fapi\u002Fv3\u002Fklines&quot;, params=params, timeout=15)\n        weight = resp.headers.get(&quot;x-mbx-used-weight-1m&quot;, &quot;?&quot;)\n        logger.info(&quot;%s: %d candles, weight=%s&quot;, symbol, len(resp.json()), weight)\n        return resp.json()\n    except httpx.HTTPStatusError as e:\n        if e.response.status_code == 429:\n            retry_after = int(e.response.headers.get(&quot;retry-after&quot;, 10))\n            logger.warning(&quot;%s: 429, waiting %ds&quot;, symbol, retry_after)\n            await asyncio.sleep(retry_after)\n        raise\n\nasync def main():\n    symbols = [&quot;BTCUSDT&quot;, &quot;ETHUSDT&quot;, &quot;BNBUSDT&quot;, &quot;SOLUSDT&quot;, &quot;XRPUSDT&quot;]\n    proxy_url = &quot;http:\u002F\u002Fuser-country-US:pass@gate.proxyhat.com:8080&quot;\n\n    semaphore = asyncio.Semaphore(MAX_CONCURRENT)\n\n    async with httpx.AsyncClient(\n        proxy=proxy_url,\n        limits=httpx.Limits(max_connections=20, max_keepalive_connections=10),\n    ) as client:\n        async def bounded_fetch(sym):\n            async with semaphore:\n                return await fetch_klines(client, sym, &quot;1m&quot;, 100)\n\n        results = await asyncio.gather(\n            *[bounded_fetch(s) for s in symbols], return_exceptions=True\n        )\n\n    for sym, res in zip(symbols, results):\n        if isinstance(res, Exception):\n            logger.error(&quot;%s failed: %s&quot;, sym, res)\n        else:\n            logger.info(&quot;%s: %d data points&quot;, sym, len(res))\n\nasyncio.run(main())\n\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Ch3>4. Python: sticky-сессия для бэкфилла исторических klines\u003C\u002Fh3>\n\u003Cp>Для пагинации исторических данных используйте \u003Cstrong>sticky-сессию\u003C\u002Fstrong> (\u003Ccode>-sid-abc123\u003C\u002Fcode>), чтобы все запросы шли через один IP. Это позволяет использовать непрерывный весовой бюджет одного IP и избегать рассинхронизации:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>import requests\nimport time\nimport logging\n\nlogging.basicConfig(level=logging.INFO, format=&quot;%(asctime)s %(levelname)s %(message)s&quot;)\nlogger = logging.getLogger(&quot;klines_backfill&quot;)\n\ndef backfill_klines(symbol: str, interval: str, start_time: int, end_time: int):\n    &quot;&quot;&quot;Бэкфилл исторических свечей через sticky-сессию ProxyHat.\n\n    Args:\n        symbol: Торговая пара, напр. &apos;BTCUSDT&apos;\n        interval: Интервал свечей, напр. &apos;1m&apos;, &apos;1h&apos;, &apos;1d&apos;\n        start_time: Unix timestamp (ms) начала периода\n        end_time: Unix timestamp (ms) конца периода\n    &quot;&quot;&quot;\n    GATE = &quot;gate.proxyhat.com:8080&quot;\n    SESSION_ID = f&quot;backfill-{symbol}-{interval}&quot;\n    proxy_url = f&quot;http:\u002F\u002Fuser-sid-{SESSION_ID}:pass@{GATE}&quot;\n    proxies = {&quot;http&quot;: proxy_url, &quot;https&quot;: proxy_url}\n\n    all_klines = []\n    current_start = start_time\n    max_per_request = 1000  # Binance максимум для klines\n    used_weight = 0\n\n    session = requests.Session()\n\n    while current_start &lt; end_time:\n        # Weight-aware throttle\n        if used_weight &gt;= 5500:\n            logger.info(&quot;Weight %d, cooling down 60s&quot;, used_weight)\n            time.sleep(60)\n            used_weight = 0\n\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;: max_per_request,\n        }\n\n        for attempt in range(5):\n            try:\n                resp = session.get(\n                    &quot;https:\u002F\u002Fapi.binance.com\u002Fapi\u002Fv3\u002Fklines&quot;,\n                    params=params, proxies=proxies, timeout=15\n                )\n\n                weight_h = resp.headers.get(&quot;X-MBX-USED-WEIGHT-1M&quot;)\n                if weight_h:\n                    used_weight = int(weight_h)\n\n                if resp.status_code == 429:\n                    wait = int(resp.headers.get(&quot;Retry-After&quot;, 10))\n                    logger.warning(&quot;429, waiting %ds&quot;, wait)\n                    time.sleep(wait)\n                    continue\n\n                resp.raise_for_status()\n                batch = resp.json()\n\n                if not batch:\n                    logger.info(&quot;No more data, stopping&quot;)\n                    return all_klines\n\n                all_klines.extend(batch)\n                # Сдвигаем startTime на время последней свечи + 1ms\n                current_start = batch[-1][6] + 1  # index 6 = closeTime\n                logger.info(&quot;Got %d candles (total %d), weight=%s, next=%d&quot;,\n                            len(batch), len(all_klines), weight_h, current_start)\n                break\n\n            except requests.RequestException as e:\n                wait = 2 ** attempt\n                logger.warning(&quot;Retry %d: %s, waiting %ds&quot;, attempt + 1, e, wait)\n                time.sleep(wait)\n        else:\n            raise RuntimeError(f&quot;Failed after 5 retries at startTime={current_start}&quot;)\n\n        # Небольшая задержка между запросами\n        time.sleep(0.1)\n\n    return all_klines\n\n# Бэкфилл BTCUSDT за 1 час (1-минутные свечи = 60 свечей)\ndata = backfill_klines(&quot;BTCUSDT&quot;, &quot;1m&quot;, 1700000000000, 1700003600000)\nlogger.info(&quot;Total candles collected: %d&quot;, len(data))\n\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Ch3>5. Node.js axios: ротация IP с retry и weight-tracking\u003C\u002Fh3>\n\u003Cp>Для JavaScript\u002FTypeScript-разработчиков — эквивалент на axios с прокси-агентом:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>const axios = require(&apos;axios&apos;);\nconst HttpsProxyAgent = require(&apos;https-proxy-agent&apos;).HttpsProxyAgent;\nconst logging = require(&apos;logging&apos;).default;\n\nconst logger = logging.getLogger(&apos;binance_node&apos;);\nconst GATE = &apos;gate.proxyhat.com:8080&apos;;\nconst BASE = &apos;https:\u002F\u002Fapi.binance.com&apos;;\n\n\u002F**\n * Клиент для скрейпинга Binance через ротацию IP ProxyHat.\n *\u002F\nclass BinanceScraper {\n  constructor(username, password, country = null) {\n    this.username = username;\n    this.password = password;\n    this.country = country;\n    this.usedWeight = 0;\n    this.maxWeightPerMin = 5500;\n  }\n\n  getProxyUrl(sessionId = null) {\n    let user = this.username;\n    if (this.country) user += `-country-${this.country}`;\n    if (sessionId) user += `-sid-${sessionId}`;\n    return `http:\u002F\u002F${user}:${this.password}@${GATE}`;\n  }\n\n  async request(path, params = {}, sessionId = null) {\n    const proxyUrl = this.getProxyUrl(sessionId);\n    const agent = new HttpsProxyAgent(proxyUrl);\n    const url = `${BASE}${path}`;\n\n    for (let attempt = 0; attempt &lt; 5; attempt++) {\n      if (this.usedWeight &gt;= this.maxWeightPerMin) {\n        logger.info(`Weight ${this.usedWeight}, cooling down 60s`);\n        await new Promise(r =&gt; setTimeout(r, 60000));\n        this.usedWeight = 0;\n      }\n\n      try {\n        const resp = await axios.get(url, {\n          params,\n          httpsAgent: agent,\n          timeout: 15000,\n        });\n\n        const weight = resp.headers[&apos;x-mbx-used-weight-1m&apos;];\n        if (weight) this.usedWeight = parseInt(weight);\n\n        return resp.data;\n      } catch (err) {\n        if (err.response) {\n          const status = err.response.status;\n          if (status === 429) {\n            const retryAfter = parseInt(err.response.headers[&apos;retry-after&apos;] || &apos;10&apos;);\n            logger.warn(`429 rate limited, waiting ${retryAfter}s`);\n            await new Promise(r =&gt; setTimeout(r, retryAfter * 1000));\n            continue;\n          }\n          if (status === 418) {\n            logger.error(&apos;418 IP banned, waiting 120s&apos;);\n            await new Promise(r =&gt; setTimeout(r, 120000));\n            continue;\n          }\n        }\n        const wait = Math.pow(2, attempt) * 1000;\n        logger.warn(`Attempt ${attempt + 1} failed: ${err.message}, retry in ${wait}ms`);\n        await new Promise(r =&gt; setTimeout(r, wait));\n      }\n    }\n    throw new Error(`Failed after 5 attempts: ${path}`);\n  }\n\n  async getKlines(symbol, interval = &apos;1m&apos;, limit = 100) {\n    return this.request(&apos;\u002Fapi\u002Fv3\u002Fklines&apos;, { symbol, interval, limit });\n  }\n\n  async getDepth(symbol, limit = 100) {\n    return this.request(&apos;\u002Fapi\u002Fv3\u002Fdepth&apos;, { symbol, limit });\n  }\n\n  async getTicker24hr(symbol = null) {\n    const params = symbol ? { symbol } : {};\n    return this.request(&apos;\u002Fapi\u002Fv3\u002Fticker\u002F24hr&apos;, params);\n  }\n}\n\n\u002F\u002F Использование\n(async () =&gt; {\n  const scraper = new BinanceScraper(&apos;user&apos;, &apos;pass&apos;, &apos;US&apos;);\n  const symbols = [&apos;BTCUSDT&apos;, &apos;ETHUSDT&apos;, &apos;BNBUSDT&apos;];\n\n  for (const sym of symbols) {\n    const klines = await scraper.getKlines(sym, &apos;5m&apos;, 100);\n    logger.info(`${sym}: ${klines.length} candles`);\n  }\n})();\n\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Ch3>6. SOCKS5 для высокочастотного поллинга depth\u003C\u002Fh3>\n\u003Cp>Для поллинга книги ордеров с высокой частотой SOCKS5-прокси может обеспечить меньшую задержку:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>import requests\nimport time\nimport logging\n\nlogging.basicConfig(level=logging.INFO, format=&quot;%(asctime)s %(levelname)s %(message)s&quot;)\nlogger = logging.getLogger(&quot;depth_poller&quot;)\n\ndef poll_depth(symbol: str, limit: int = 100, interval_sec: float = 0.5):\n    &quot;&quot;&quot;Поллинг книги ордеров через SOCKS5 ProxyHat с ротацией IP.&quot;&quot;&quot;\n    socks_proxy = &quot;socks5:\u002F\u002Fuser-country-US:pass@gate.proxyhat.com:1080&quot;\n    proxies = {&quot;http&quot;: socks_proxy, &quot;https&quot;: socks_proxy}\n    session = requests.Session()\n    used_weight = 0\n\n    while True:\n        if used_weight &gt;= 5500:\n            logger.info(&quot;Weight %d, cooling down&quot;, used_weight)\n            time.sleep(60)\n            used_weight = 0\n\n        try:\n            resp = session.get(\n                &quot;https:\u002F\u002Fapi.binance.com\u002Fapi\u002Fv3\u002Fdepth&quot;,\n                params={&quot;symbol&quot;: symbol, &quot;limit&quot;: limit},\n                proxies=proxies, timeout=10\n            )\n            weight_h = resp.headers.get(&quot;X-MBX-USED-WEIGHT-1M&quot;)\n            if weight_h:\n                used_weight = int(weight_h)\n\n            if resp.status_code == 429:\n                wait = int(resp.headers.get(&quot;Retry-After&quot;, 10))\n                logger.warning(&quot;429, waiting %ds&quot;, wait)\n                time.sleep(wait)\n                continue\n\n            data = resp.json()\n            bids_count = len(data.get(&quot;bids&quot;, []))\n            asks_count = len(data.get(&quot;asks&quot;, []))\n            logger.info(&quot;%s depth: %d bids \u002F %d asks, weight=%s&quot;,\n                        symbol, bids_count, asks_count, weight_h)\n\n        except Exception as e:\n            logger.error(&quot;Error: %s&quot;, e)\n\n        time.sleep(interval_sec)\n\n# poll_depth(&quot;BTCUSDT&quot;, limit=100, interval_sec=0.5)\n\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Ch2>Когда WebSocket лучше REST-поллинга\u003C\u002Fh2>\n\u003Cp>Binance предоставляет публичные WebSocket-стримы на \u003Ccode>wss:\u002F\u002Fstream.binance.com:9443\u002Fws\u003C\u002Fcode> для данных в реальном времени. Для непрерывного мониторинга книги ордеров или свечей WebSocket эффективнее REST-поллинга:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>REST-поллинг\u003C\u002Fstrong> — подходит для периодического сбора, бэкфилла истории, snapshot-ов. Каждый запрос тратит вес.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>WebSocket\u003C\u002Fstrong> — одно соединение, push-обновления без расхода веса. Идеально для real-time orderbook и kline-streams.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>Используйте REST через прокси для исторических данных и snapshot-ов, а WebSocket — для live-streaming. Прокси ProxyHat поддерживают как HTTP, так и SOCKS5 для обоих сценариев.\u003C\u002Fp>\n\n\u003Ch2>Распространённые ошибки и edge-cases\u003C\u002Fh2>\n\u003Cul>\n\u003Cli>\u003Cstrong>Игнорирование заголовка веса\u003C\u002Fstrong> — всегда читайте \u003Ccode>X-MBX-USED-WEIGHT-1M\u003C\u002Fcode> и throttling'те до исчерпания лимита, а не после.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Отсутствие retry-логики для 429\u002F418\u003C\u002Fstrong> — без обработки \u003Ccode>Retry-After\u003C\u002Fcode> вы получите бан 418.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Слишком высокий параллелизм\u003C\u002Fstrong> — 100+ одновременных запросов с одного IP исчерпают вес за секунды. Ограничивайте concurrency семафором.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Геоблок 451\u003C\u002Fstrong> — если целевой эндпоинт возвращает 451, используйте \u003Ccode>-country-US\u003C\u002Fcode> или другую страну в имени пользователя ProxyHat.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Смешивание сессий\u003C\u002Fstrong> — для пагинации klines используйте одну sticky-сессию, чтобы вес накапливался на одном IP предсказуемо.\u003C\u002Fli>\n\u003C\u002Ful>\n\n\u003Ch2>Настройка ProxyHat и внутренние ссылки\u003C\u002Fh2>\n\u003Cp>ProxyHat предоставляет резидентные, мобильные и дата-центр прокси с гибким геотаргетингом. Для скрейпинга Binance API рекомендуем \u003Cstrong>резидентные прокси\u003C\u002Fstrong> — они выглядят как реальные пользовательские IP и снижают риск блокировок. Конфигурация проста:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>HTTP-прокси:\u003C\u002Fstrong> \u003Ccode>http:\u002F\u002FUSERNAME:PASSWORD@gate.proxyhat.com:8080\u003C\u002Fcode>\u003C\u002Fli>\n\u003Cli>\u003Cstrong>SOCKS5-прокси:\u003C\u002Fstrong> \u003Ccode>socks5:\u002F\u002FUSERNAME:PASSWORD@gate.proxyhat.com:1080\u003C\u002Fcode>\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Геотаргетинг:\u003C\u002Fstrong> добавьте \u003Ccode>-country-US\u003C\u002Fcode> или \u003Ccode>-country-DE-region-state_of_berlin-city-berlin\u003C\u002Fcode> к имени пользователя\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Sticky-сессия:\u003C\u002Fstrong> добавьте \u003Ccode>-sid-abc123\u003C\u002Fcode> для закрепления IP\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>Подробнее о тарифах — на странице \u003Ca href=\"\u002Fru\u002Fpricing\">цен ProxyHat\u003C\u002Fa>. Доступные локации — на странице \u003Ca href=\"\u002Fru\u002Flocations\">локаций прокси\u003C\u002Fa>. Use-case для веб-скрейпинга — \u003Ca href=\"\u002Fru\u002Fuse-cases\u002Fweb-scraping\">веб-скрейпинг через ProxyHat\u003C\u002Fa>, для SERP-трекинга — \u003Ca href=\"\u002Fru\u002Fuse-cases\u002Fserp-tracking\">SERP-трекинг\u003C\u002Fa>. Полная техническая документация — на \u003Ca href=\"https:\u002F\u002Fdocs.proxyhat.com\u002F\" rel=\"noopener noreferrer\">docs.proxyhat.com\u003C\u002Fa>.\u003C\u002Fp>\n\n\u003Ch2>Ключевые выводы\u003C\u002Fh2>\n\u003Cblockquote>\n\u003Cul>\n\u003Cli>\u003Cstrong>Вес — ключевой ресурс:\u003C\u002Fstrong> Binance даёт ~6000 веса\u002Fмин на IP. Отслеживайте \u003Ccode>X-MBX-USED-WEIGHT-1M\u003C\u002Fcode> и throttling'те до лимита.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Ротация IP распределяет вес:\u003C\u002Fstrong> N IP-адресов = N × 6000 веса\u002Fмин. Резидентные прокси ProxyHat через \u003Ccode>gate.proxyhat.com:8080\u003C\u002Fcode> — простое решение.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Sticky-сессии для пагинации:\u003C\u002Fstrong> используйте \u003Ccode>-sid-ID\u003C\u002Fcode> для бэкфилла klines, чтобы вес накапливался предсказуемо.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Геотаргетинг решает 451:\u003C\u002Fstrong> \u003Ccode>-country-US\u003C\u002Fcode> обходит геоблок Binance.com в США.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>WebSocket для real-time:\u003C\u002Fstrong> для live-orderbook и kline-streams используйте \u003Ccode>wss:\u002F\u002Fstream.binance.com\u003C\u002Fcode>, а не REST-поллинг.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Retry + backoff обязателен:\u003C\u002Fstrong> обработка 429 с \u003Ccode>Retry-After\u003C\u002Fcode> и экспоненциальная задержка предотвращают бан 418.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003C\u002Fblockquote>","Весовые лимиты API криптобирж и прокси (Binance) | ProxyHat","Руководство по сбору рыночных данных Binance REST API через резидентные прокси: эндпоинты, весовые лимиты, ротация IP, код на Python и Node.js.","\u002Fru\u002Fblog\u002Fkak-skrejpit-binance-rest-api-proksi",null,"Рыночные данные криптобирж: весовые лимиты и прокси | ProxyHat","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fru\u002Fkak-skrejpit-binance-rest-api-proksi-og.webp",[18,21,24,27,30],{"question":19,"answer":20},"Что такое скрейпинг Binance REST API через прокси?","Это сбор публичных рыночных данных (свечи, книга ордеров, тикеры) с эндпоинтов api.binance.com\u002Fapi\u002Fv3\u002F через прокси-серверы, которые распределяют запросы по нескольким IP-адресам. Это позволяет обойти весовое ограничение ~6000 единиц в минуту на один IP и собирать данные в большем масштабе.",{"question":22,"answer":23},"Зачем нужны прокси для скрейпинга Binance API?","Binance применяет весовые лимиты на IP. С одного адреса вы ограничены ~6000 веса\u002Fмин, а за превышение следует HTTP 429, а затем бан 418. Ротация резидентных прокси через gate.proxyhat.com:8080 распределяет вес по пулу IP, каждый из которых получает свой бюджет. Также геотаргетинг -country-US решает проблему HTTP 451 при доступе из США.",{"question":25,"answer":26},"Какой тип прокси лучше для скрейпинга Binance?","Резидентные прокси оптимальны — они используют IP реальных интернет-провайдеров и реже блокируются антибот-системами. Дата-центр прокси быстрее, но чаще распознаются. Для бэкфилла истории с пагинацией используйте sticky-сессии (-sid-ID), а для параллельного сбора по множеству символов — ротацию IP без сессии.",{"question":28,"answer":29},"Как избежать блокировок при скрейпинге Binance API?","Отслеживайте заголовок X-MBX-USED-WEIGHT-1M и делайте паузу до достижения лимита 6000. Обрабатывайте HTTP 429 с заголовком Retry-After и применяйте экспоненциальную задержку. Ограничивайте параллелизм семафором (10–20 одновременных запросов). Не игнорируйте 429 — многократные нарушения приводят к бану 418 на срок от 2 минут до нескольких дней.",{"question":31,"answer":32},"Когда использовать WebSocket вместо REST для Binance?","WebSocket (wss:\u002F\u002Fstream.binance.com:9443\u002Fws) эффективнее для непрерывного мониторинга real-time данных — orderbook updates, kline streams. Одно соединение получает push-обновления без расхода веса. REST через прокси оптимален для бэкфилла истории, snapshot-ов и периодического сбора.",false,"2026-08-03T10:04:04+00:00","2026-10-04T02:43:17+00:00","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fru\u002Fkak-skrejpit-binance-rest-api-proksi-master.webp","How to Scrape the Binance REST API with Proxies: A Developer Guide","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fru\u002Fkak-skrejpit-binance-rest-api-proksi-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,"rukovodstva-dlya-razrabotchikov","Руководства для разработчиков","Руководства для разработчиков | Блог ProxyHat","Туториалы по коду и SDK для интеграции прокси в ваши приложения.",[],{"fr":53,"pt":54,"ko":55,"ru":13,"en":56,"zh":57,"x-default":56},"\u002Ffr\u002Fblog\u002Fcomment-scraper-api-rest-binance-proxies","\u002Fpt\u002Fblog\u002Fcomo-raspar-api-binance-proxies","\u002Fko\u002Fblog\u002Fbinance-rest-api-proxy-scraping","\u002Fblog\u002Fscrape-binance-rest-api-proxies","\u002Fcn\u002Fblog\u002Fbinance-rest-api-proxy-scraping-guide",{"tr":59,"fr":53,"ja":60,"pt":54,"ko":55,"pl":61,"es":62,"ru":13,"en":56,"zh":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,"nastrojka-proksi-dlya-ai-agentov","Прокси для AI-агентов: browser-use, Crawl4AI и MCP-сервер","Агенты на облачных виртуалках выходят в сеть с IP дата-центров. Даём актуальную рабочую настройку прокси для browser-use, Crawl4AI и MCP-сервера, таблицу выбора между sticky и ротацией и разбираем ловушки, на которых сгорает бюджет.","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fru\u002Fnastrojka-proksi-dlya-ai-agentov-master.webp","Proxy Setup for AI Agents: browser-use, Crawl4AI and an MCP Server","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fru\u002Fnastrojka-proksi-dlya-ai-agentov-card.webp","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fru\u002Fnastrojka-proksi-dlya-ai-agentov-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,"veb-skraping","Веб-скрапинг",{"id":89,"slug":90,"name":91},2,"rezidentskie-proksi","Резидентские прокси",{"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-rezidentnye-proksi-python","Camoufox с резидентными прокси: практическое руководство на Python","Как запустить Camoufox — Firefox с патчами на C++ — за резидентными прокси: актуальный Python API, почему geoip нужна sticky-сессия, чек-лист согласованности отпечатка и когда лучше подойдут Patchright или nodriver.","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fru\u002Fcamoufox-rezidentnye-proksi-python-master.webp","Camoufox with Residential Proxies: A Code-First Python Guide","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fru\u002Fcamoufox-rezidentnye-proksi-python-card.webp","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fru\u002Fcamoufox-rezidentnye-proksi-python-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-obnaruzhenie","Анти-обнаружение",{"id":93,"slug":94,"name":95},{"id":124,"slug":125,"name":126},21,"bezgolovnyj-brauzer","Headless-браузер",{"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-residential-proxies","got-scraping в Node.js: руководство по парсингу с резидентными прокси","Практическое руководство для Node.js-разработчиков: как использовать got-scraping с генератором заголовков, HTTP\u002F2 и резидентными прокси ProxyHat для масштабного парсинга без блокировок.","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fru\u002Fgot-scraping-nodejs-residential-proxies-master.webp","got-scraping in Node.js: A Developer's Guide with Residential Proxies","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fru\u002Fgot-scraping-nodejs-residential-proxies-card.webp","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fru\u002Fgot-scraping-nodejs-residential-proxies-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,"rotaciya-proksi-v-colly-1","Ротация прокси в Colly: Полное руководство для Go-разработчиков","Практическое руководство по ротации прокси в Colly — от встроенного RoundRobinProxySwitcher до кастомных SetProxyFunc с резидентными IP. Примеры кода, продакшн-паттерны и типичные ошибки.","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fru\u002Frotaciya-proksi-v-colly-1-master.webp","Rotating Proxies in Colly: A Framework-Idiomatic Guide for Go Developers","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fru\u002Frotaciya-proksi-v-colly-1-card.webp","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fru\u002Frotaciya-proksi-v-colly-1-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},[],[]]