Вход Регистрация

Прокси

Node-fetch + HTTP-прокси: как собирать данные без блокировок

Полный пример использования node-fetch с HTTP-прокси: как настроить сбор данных с прокси-сервером, обойти ограничения и защититься от блокировок при парсинге.

Команда Froxy 22 июл 2025 6 мин
Node-fetch + HTTP-прокси: как собирать данные без блокировок

Современные проекты на JavaScript чаще всего работают на удалённых серверах, в среде Node.js. При обмене данными между скриптами (обычно по API-интерфейсу), а также при сборе информации с внешних сайтов (скрапинге) разработчикам нужен простой и надёжный способ отправлять HTTP-запросы. И хотя на рынке существует много библиотек для этих целей, встроенная node-fetch стала одной из самых популярных благодаря своей простоте и схожести с браузерным Fetch API.

В этой статье мы разберём, что такое node-fetch, чем удобна эта библиотека и какие ограничения у неё есть, а также покажем примеры использования node-fetch с прокси.

Что такое node-fetch и почему разработчики его используют

Node-fetch – это встроенная библиотека фреймворка Node.js, которая в синтаксисе подражает дефолтному API-интерфейсу браузеров для JavaScript-кода (Fetch API). Ранее компонент node-fetch поставлялся отдельно и требовал ручной установки, но с 2022 года включён в стандартный установочный пакет Node.js (18 версия и выше).

Разработчики используют node-fetch как наиболее простую и лёгкую альтернативу сторонних HTTP-клиентов при работе с HTTP-запросами и ответами. Например, с её помощью можно организовать обмен данными с удалённым веб-сервисом или создать API для своей программы (при обмене информацией и файлами с внешними клиентами). Через node-fetch можно взаимодействовать с CLI-утилитами.

Особо стоит отметить то, что node-fetch из коробки поддерживает асинхронность и промисы. Но давайте обо всё по порядку.

Основы node-fetch

Node-fetch – это, если упростить, HTTP-клиент, который позволяет отправлять запросы и получать ответ сервера, например, HTML-код, JSON, файл и т.д. Никакие дополнительные программы и библиотеки для этого не нужны.

Когда вы вызываете node-fetch из своих JS-скриптов, то библиотека:

  1. Отправляет HTTP-запрос.
  2. Получает «сырой» HTML (как если бы вы открыли исходный код страницы в блокноте).
  3. Возвращает этот HTML как текст.

Без дополнительных параметров node-fetch по умолчанию отправляет GET-запросы. Но тип запроса можно сменить на любой другой (POST, PUT, DELETE).

Node-fetch не загружает никакие скрипты (имеются ввиду те, что задействуются при рендеринге страниц в классическом браузере), не выполняет их, не строит DOM-структуру документа и не отображает страниц. Она никаким образом не взаимодействует ни с какими браузерами (в том числе с headless-браузерами).

Собственно, функция fetch() в браузерах реализует ту же функцию, ведь это тоже штатный HTTP-клиент.

Удобнее всего с помощью node-fetch обмениваться форматированными данными с удалёнными серверами и сайтами, например, JSON или XML. В этом случае ответ легко будет разобрать на мелкие составляющие.

Простейший пример асинхронного использования node-fetch

Если вы используете старую версию Node.js (меньше 18 версии), то сначала нужно установить библиотеку:

npm install node-fetch

Создайте простой текстовый файл и смените ему расширение на .js. Пусть будет «node-fetch.js. Наполните файл содержимым:

// Здесь мы импортируем библиотеку node-fetch в свой проектimport fetch from 'node-fetch';// Отправляем GET-запрос через функцию fetch (), тип запроса указывать не нужно, он используется по дефолтуconst response = await fetch('https://my-target.site.com/posts/1');// Преобразуем ответ сервера в текстconst body = await response.text();// Выводим ответ в консольconsole.log (body);

 

Запустите свой скрипт (команда для консоли):

node node-fetch.js

Примерно так выглядит POST-запрос (например, для отправки данных для публикации в блоге):

// Здесь мы импортируем библиотеку node-fetch в свой проектimport fetch from 'node-fetch';// Явно указываем тип запроса POST и его содержимоеconst response = await fetch('https://my-target.site.com/post', {method: 'POST', body: 'My first post from node-fetch'});// На всякий случай забираем ответ сервера в JSON-формате…const data = await response.json();// И выводим его в консольconsole.log(data);

 

Библиотека node-fetch отлично работает с ошибками (для отладки) и HTTP-заголовками.

Node-fetch для веб-скрапинга: плюсы и ограничения

  • Node-fetch для веб-скрапинга

Node-fetch вполне подходит для простейших задач веб-скрапинга – в роли лёгкого и удобного инструмента для отправки HTTP-запросов и получения исходного HTML-кода страниц.

Преимущества node-fetch для парсинга можно обозначить так:

  • Это штатная библиотека Node.js, ничего дополнительно устанавливать не нужно.
  • Синтаксис максимально соответствует Fetch-API браузеров. Не нужно изучать специфические команды, операторы и их параметры.
  • Node-fetch потребляет минимум ресурсов.
  • С помощью библиотеки можно быстро получить исходный HTML-код целевых страниц, а также обменяться форматированными данными (JSON, XML и т.п.).
  • Node-fetch поддерживает отладку и работу не только с HTTP-заголовками, но и с конкретными метаданными (статусы, куки, редиректы, кодировка, User-Agent и т.п.).
  • Работа с промисами и асинхронность из коробки.
  • Наличие расширений и плагинов, например, для работы со сжатием, счётчиками и т.п.).

К недостаткам node-fetch можно отнести:

  • Из-за особенностей архитектуры Node.js, библиотека node-fetch не умеет работать с кешем и некоторыми свойствами подключений (keepalive, destination, integrity, mode, type и т.п.).
  • В качестве целевых URL нельзя передавать относительные адреса, только абсолютные.
  • Node-fetch не умеет рендерить страницы, то есть она всегда работает только с исходным кодом. Для парсинга современных сайтов и веб-приложений это может быть критичной проблемой. А через headless-браузер node-fetch не перенаправить. Для понимания контраста изучите материал по парсингу с Puppeteer.
  • В node-fetch нет функций для поиска отдельного контента. Для этого ответ сервера придётся разбирать сторонними синтаксическими анализаторами.
  • Из коробки в node-fetch нет поддержки прокси.

Почему скрапинг часто требует прокси

Прокси для скрапинга – это не просто рекомендация, а критическая необходимость. Дело в том, что многие современные сайты быстро выявляют автоматический трафик и блокируют его, чтобы снизить нагрузку и исключить доступ к чувствительному контенту. Первое, что анализируется – это IP-адрес пользователя и количество его подключений. Большое число обращений с одного и того же IP легко выявляется, в результате адрес попадает в бан (временный или постоянный, в зависимости от типа адреса).

Эффективно бороться с такими блокировками позволяют ротируемые прокси (резидентные, а ещё лучше мобильные). Если не использовать прокси, то процесс парсинга может существенно растянуться по времени или полностью остановиться в любой момент. Прокси не только помогают с обходом блокировок, но и обеспечивают параллельное выполнение большого числа запросов, ускоряя процесс. А ещё за счёт смены расположения IP (подбора прокси в нужных локациях) можно обходить географические ограничения и получать доступ к региональным библиотекам контента.

Конечно, одних только прокси недостаточно, но они являются базовым условием для выстраивания всех остальных средств обхода механизмов защиты целевых сайтов.

Резидентные прокси

Лучшие прокси-серверы для доступа к ценным данным со всего мира.

Получить триал $1.99, 100Mb

Node-fetch не поддерживает прокси изначально – вот почему

Библиотека node-fetch специально спроектирована как минималистичный инструмент: она не содержит встроенного функционала для работы через прокси, чтобы оставаться лёгкой и простой в обиходе.

При отправке запросов node-fetch полагается на системные настройки сетевого подключения хоста. То есть чисто технически, если вам нужно запустить коннект через прокси-сервер, вы можете это сделать на уровне настроек операционной системы.

По аналогии: в браузерном API-fetch тоже нет поддержки прокси, fetch() полагается на настройки браузера или ОС.

В рамках 100% соответствия синтаксиса действия разработчиков node-fetch можно считать более чем разумными.

Но неудобными…

К слову, в Node.js тоже нет никаких встроенных механизмов для работы через прокси. Как исправить эту несправедливость, опишем ниже.

Использование node-fetch с HTTP-прокси

node-fetch с HTTP-прокси

Чтобы подружить node-fetch с прокси, вам по факту нужно будет изменить агент подключения для каждого типа запросов: http, https, socks, – для всей среды Node.js.

Это делается через параметр agent, вам потребуются дополнительные пакеты-агенты, например:

  • https-proxy-agent
  • http-proxy-agent
  • socks-proxy-agent (если нужен SOCKS)

Пример: Отправка запроса через HTTP-прокси с https-proxy-agent

// Импортируем библиотеку node-fetch и https-proxy-agentimport fetch from 'node-fetch';import HttpsProxyAgent from 'https-proxy-agent';// Прописываем актуальный адрес вашего проксиconst proxyAgent = new HttpsProxyAgent('http://YOURPROXYLOGIN:PSSWRD@YOUR-PROXYHOST:PORT');// Задействуем асинхронность(async () => {// Отправляем запрос к целевому сайтуconst response = await fetch('https://target-site.com', {// В качестве агента выбираем наш проксиagent: proxyAgent});// Получаем ответ в виде текстаconst text = await response.text();// Выводим этот текст в лог консолиconsole.log(text);})();

Обратите внимание: node fetch proxy работают через «агента», раздувать код не нужно (одна библиотека – одна задача), а «агента» легко заменить на любого другого: http, https, socks, что-то своё.

Пример: Ротация HTTP-прокси в скрипте скрапера

// Импортируем библиотеку node-fetch и https-proxy-agentimport fetch from 'node-fetch';import HttpsProxyAgent from 'https-proxy-agent';// Список прокси (укажите здесь свои адреса)let proxyList = ['http://user1:pass1@proxy1.example.com:8080','http://user2:pass2@proxy2.example.com:8080','http://user3:pass3@proxy3.example.com:8080'];// Реализация функции случайного выбора проксиfunction getRandomProxy() {const index = Math.floor(Math.random() * proxyList.length);return proxyList[index];}// Функция для удаления плохого (нерабочего) проксиfunction removeBadProxy(badProxy) {proxyList = proxyList.filter(proxy => proxy !== badProxy);// Дополнительно выводим данные о плохом прокси в консольconsole.log(`Proxy removed: ${badProxy}`);}// Функция отправки запроса с ротацией проксиasync function scrapeWithProxy(url) {// Если в списке нет прокси, останавливаем парсингif (proxyList.length === 0) {// А в консоль пишем, что прокси закончилисьconsole.log('No available proxies left');return;}// Тут обращаемся к функции выбора случайного проксиconst proxy = getRandomProxy();// Отправляем запрос через агентаconst agent = new HttpsProxyAgent(proxy);try {// На всякий случай добавляем таймаут, чтобы не ждать «вечную» загрузкуconst res = await fetch(url, { agent, timeout: 10000 }); // 10 секунд // Если ответ сервера содержит ошибкуif (!res.ok) {// Идентифицируем еёthrow new Error(`HTTP error: ${res.status}`);}// Сохраняем ответ в виде текстаconst text = await res.text();// Выводим в консоль информацию об успешном коннекте, и в качестве подтверждения считаем число символов в ответеconsole.log(`Response from proxy ${proxy.substring(0, 30)}...: received ${text.length} characters`);// Ловим ошибку} catch (err) {// Выводим в консоль данные о проблемном подключении и дополняем его содержимым ошибкиconsole.error(`Error with proxy ${proxy.substring(0, 30)}...:`, err.message);// Удаляем из списка плохой проксиremoveBadProxy(proxy);}}// Пример списка целевыхURL, замените на своиconst urls = ['https://httpbin.org/ip','https://httpbin.org/headers','https://httpbin.org/user-agent'];// Запуск скрапинга по списку URL(async () => {for (const url of urls) {// Если список прокси пустой, то останавливаем процесс и пишем об этом в консолиif (proxyList.length === 0) {console.log('Stopped: all proxies are unavailable');break;}// Если ошибок нет, выполняем парсингawait scrapeWithProxy(url);}})();При каждой ошибке, например, при ошибке соединения и др., node-fetch http proxy автоматически удаляется из списка. Если список прокси становится пустым, скрипт останавливается. В консоль выводятся данные о том, какой прокси был удалён и с какой ошибкой. Таймаут исключает ситуацию зависания с неотвечающим прокси.

Пример: Использование socks-proxy-agent для доступа к заблокированным ресурсам

В отличие от высокоуровневых HTTP/HTTPS-прокси, SOCKS-прокси работают на транспортном уровне OSI и не вмешиваются в HTTP-заголовки. Что в свою очередь обеспечивает максимальную конфиденциальность и отсутствие каких-либо технических признаков работы через сторонние узлы.

Пример скрипта node-fetch с прокси на основе SOCKS5-протокола (если профильная библиотека отсутствует, предварительно установите её командой «npm install socks-proxy-agent»):

// Импортируем библиотеку node-fetch и https-proxy-agentimport fetch from 'node-fetch';import { SocksProxyAgent } from 'socks-proxy-agent';// Пример SOCKS-прокси (можно использовать свой)const socksProxy = 'socks5h://127.0.0.1:9050'; // здесь мы показали вариант локального Tor-прокси// Создаём «агента» SOCKSconst agent = new SocksProxyAgent(socksProxy);// Целевой URL, к которому нужно обратиться (может быть заблокирован без прокси)const targetUrl = 'https://httpbin.org/ip';// Здесь описывается логика асинхронной функции запросаasync function fetchThroughSocks() {try {// Тут отправляем запрос через 'node-fetch' с использованием агента и таймаутаconst res = await fetch(targetUrl, { agent, timeout: 10000 }); // Таймаут 10 секунд, можно заменить на своё значение// Если ресурс недоступен…if (!res.ok) {// Забираем описание ошибкиthrow new Error(`HTTP error: ${res.status}`);}// Ответ сохраняем в виде простого текстаconst data = await res.text();// В консоль выводим полученные данныеconsole.log(`Response received: ${data}`);// Если «поймали» ошибку} catch (err) {// Выводим сообщение об ошибкеconsole.error(`Error: ${err.message}`);}}// Запуск нашей функцииfetchThroughSocks();

Заключение и рекомендации

node-fetch с прокси

Работу библиотеки node-fetch с прокси легче всего настроить через агента. Он в свою очередь может работать по протоколу HTTP, HTTPS или SOCKS. Примеры скриптов для каждого из вариантов мы показали выше.

Сама библиотека node-fetch во многом заменяет простейший HTTP-клиент, благодаря которому можно обмениваться запросами и данными между своими скриптами или с внешними web-приложениями без задействования «тяжёлых» комбинаций, построенных на основе полноценных или headless-браузеров в связке с API. Но node-fetch не умеет рендерить код страницы как браузер, поэтому подходит только для простейших задач.

Основная проблема – это даже не настройка агента, а сами прокси. От их качества, места расположения и надёжности будет зависеть эффективность работы вашего скрипта. Выбирайте Froxy на роль своего прокси-провайдера и не пожалеете: более 10 млн. IP в сети, 200+ стран присутствия, серверные, резидентные и мобильные прокси с автоматической ротацией. Для типовых бизнес-задач есть готовые облачные парсеры.

Получайте уведомления о новых функциях и обновлениях Froxy

Узнайте первыми о новых функциях Froxy, чтобы оставаться в курсе событий происходящих на рынке цифровых технологий и получать новости о новых функциях Froxy.

Статьи по Теме

Почему без прокси вы тратите больше, чем думаете

Прокси

Почему без прокси вы тратите больше, чем думаете

Узнайте, как отсутствие прокси-серверов увеличивает затраты: от блокировок и потерь в скрапинге до неэффективной автоматизации. Примеры и решения...

Команда Froxy 4 июн 2025 5 мин
Решение ошибки Facebook

Прокси

Решение ошибки Facebook "Session Expired" с помощью прокси

В этой статье описаны причины распространенной ошибки Facebook 'Session Expired', роль прокси-серверов в ее устранении, а также приведены инструкции...

Команда Froxy 25 янв 2024 3 мин