---
title: "استفاده از پروکسی در Node.js با Axios و node-fetch"
description: "شیوه استفاده از پروکسی در Node.js با Axios، node-fetch و fetch داخلی را با کد قابل اجرا نشان می‌دهیم؛ همراه احراز هویت، SOCKS5، چرخش IP و مدیریت خطا."
url: https://proxynet.io/fa/blog/nodejs-proxy
date: 2026-09-13
author: "Acar Diveroli"
category: "آموزش‌ها, یکپارچه‌سازی"
lang: fa
---

# استفاده از پروکسی در Node.js با Axios و node-fetch

در پایتون، تنظیم پروکسی در بیشتر کتابخانه‌ها یک پارامتر `proxies` است. در Node.js کار آشفته‌تر است: `fetch` داخلی، Axios و node-fetch پروکسی را با سه سازوکار متفاوت می‌گیرند، SOCKS5 بسته جداگانه‌ای لازم دارد و وقتی گزینه نادرستی به کتابخانه بدهید اغلب حتی خطا هم نمی‌گیرید؛ درخواست بی‌صدا بدون پروکسی خارج می‌شود. به همین دلیل مهم است بدانید کدام کتابخانه کدام گزینه را می‌خواند.

در این نوشته سه روش پایه تنظیم پروکسی در Node.js (متغیر محیطی، agent و dispatcher)، استفاده از پروکسی دارای احراز هویت با fetch داخلی، Axios و node-fetch، پروکسی‌های SOCKS5 و چرخش IP همراه تلاش دوباره را با کد قابل اجرا بررسی می‌کنیم. نمونه‌ها را روی Node.js 24 در برابر پروکسی آزمون محلی که نام کاربری و رمز می‌خواست اجرا کردیم و ناسازگاری نسخه‌ای که با آن روبه‌رو شدیم و تفاوت نمایش خطاهای احراز هویت در کتابخانه‌ها را یادداشت کردیم.

> **نکته: پاسخ کوتاه**
>
> برای fetch داخلی، `fetch` و `ProxyAgent` از بسته undici را با هم به کار ببرید یا Node.js را با `NODE_USE_ENV_PROXY=1` و متغیر محیطی `HTTPS_PROXY` اجرا کنید. در Axios برای آدرس‌های HTTPS، agent ساخته‌شده با `https-proxy-agent` را به‌عنوان `httpsAgent` بدهید و `proxy: false` را تنظیم کنید. در node-fetch همان agent در گزینه `agent` قرار می‌گیرد. برای SOCKS5 از بسته `socks-proxy-agent` استفاده کنید.

## راه‌های تنظیم پروکسی در Node.js

Node.js سه سازوکار برای فرستادن درخواست HTTP از طریق پروکسی دارد. کتابخانه‌ای که به کار می‌برید تعیین می‌کند کدام سازوکار اعمال شود.

1. **متغیر محیطی.** متغیرهای `HTTP_PROXY`، `HTTPS_PROXY` و `NO_PROXY`. کل یک اسکریپت را بدون تغییر کد از پروکسی عبور می‌دهند، اما همه کتابخانه‌ها آن‌ها را نمی‌خوانند.
2. **Agent.** ماژول‌های کلاسیک `http` و `https` در Node.js اتصال را از طریق شیء `Agent` باز می‌کنند. Axios و node-fetch از این ماژول‌ها استفاده می‌کنند، پس وقتی agent متصل به پروکسی (مانند `HttpsProxyAgent`) به آن‌ها بدهید، درخواست‌ها از پروکسی می‌گذرند.
3. **Dispatcher.** تابع `fetch` داخلی Node.js از ماژول کلاسیک `http` استفاده نمی‌کند، بلکه کلاینتی به نام undici را به کار می‌برد. در undici شیئی که اتصال‌ها را مدیریت می‌کند `dispatcher` نام دارد و برای پروکسی به آن `ProxyAgent` می‌دهید.

این تمایز مهم‌ترین نکته نوشته است: **fetch داخلی گزینه `agent` را نمی‌شناسد.** اگر از روی عادت Axios بنویسید `fetch(url, { agent })`، هیچ خطایی نمی‌گیرید و درخواست بدون پروکسی خارج می‌شود.

سازوکار کلی پروکسی و تونل `CONNECT` که برای درخواست‌های HTTPS ساخته می‌شود را در [سرور پروکسی چیست و چگونه کار می‌کند؟](/fa/blog/what-is-a-proxy-server) توضیح داده‌ایم. برگرداندن فرمان‌های cURL به fetch و Axios (هدرها، بدنه، داده فرم) موضوع نوشته [cURL در جاوااسکریپت](/fa/blog/curl-in-javascript) است؛ این نوشته فقط بر سمت پروکسی تمرکز دارد.

## چگونه با fetch داخلی از پروکسی استفاده کنیم؟

### ProxyAgent در undici

بسته undici را نصب کنید:

```bash
npm install undici
```

سپس `fetch` و `ProxyAgent` را **از همان یک بسته** وارد کنید:

```javascript
import { fetch, ProxyAgent } from "undici";

const dispatcher = new ProxyAgent("http://user:pass@pr.proxynet.io:8000");

const res = await fetch("https://httpbin.org/ip", {
  dispatcher,
  signal: AbortSignal.timeout(20_000),
});
console.log(res.status, await res.json());
```

با اینکه آدرس پروکسی با `http://` آغاز می‌شود، با خیال راحت به سایت‌های HTTPS می‌رسید: `ProxyAgent` با پروکسی تونل `CONNECT` باز می‌کند و اتصال TLS با مقصد درون همین تونل برقرار می‌شود.

**دام ناسازگاری نسخه.** Node.js نسخه undici خودش را درون خود دارد؛ undici که از npm نصب می‌کنید ممکن است تازه‌تر باشد. وقتی `ProxyAgent` بسته npm را به `fetch` **داخلی** Node.js دادیم (یعنی `fetch` سراسری را بدون import به کار بردیم)، درخواست روی Node.js 24.11 همراه undici 8.10 با خطای `fetch failed` ناموفق شد و علت آن `invalid onRequestStart method` بود. به کار بردن همان agent با `fetch` خود undici بی‌مشکل کار کرد. قاعده ساده است: `fetch` را از همان بسته‌ای بردارید که `ProxyAgent` را برداشته‌اید.

برای اینکه همه فراخوانی‌های `fetch` از undici در برنامه از یک پروکسی استفاده کنند، می‌توانید dispatcher سراسری تعریف کنید:

```javascript
import { fetch, ProxyAgent, setGlobalDispatcher } from "undici";

setGlobalDispatcher(new ProxyAgent("http://user:pass@pr.proxynet.io:8000"));

const res = await fetch("https://httpbin.org/ip"); // لازم نیست dispatcher بدهید
```

### متغیر محیطی NODE_USE_ENV_PROXY

در نسخه‌های فعلی Node.js، وقتی `NODE_USE_ENV_PROXY` روشن باشد، fetch داخلی متغیرهای محیطی استاندارد پروکسی را می‌خواند. بر اساس [راهنمای پیکربندی شبکه سازمانی](https://nodejs.org/learn/http/enterprise-network-configuration) در Node.js این قابلیت از نسخه‌های 22.21.0 و 24.5.0 در دسترس است و همین رفتار را می‌توان با گزینه خط فرمان `--use-env-proxy` هم روشن کرد.

در لینوکس و macOS:

```bash
NODE_USE_ENV_PROXY=1 HTTPS_PROXY="http://user:pass@pr.proxynet.io:8000" node app.mjs
```

در Windows PowerShell:

```powershell
$env:NODE_USE_ENV_PROXY = "1"
$env:HTTPS_PROXY = "http://user:pass@pr.proxynet.io:8000"
node app.mjs
```

این روش به تغییر کد نیاز ندارد؛ `fetch("https://httpbin.org/ip")` مستقیم از پروکسی می‌گذرد. در آزمون ما، وقتی همان فرمان بدون `NODE_USE_ENV_PROXY` اجرا شد، با وجود تنظیم `HTTPS_PROXY` درخواست هرگز به پروکسی نرسید. آدرس‌های شبکه داخلی را می‌توانید با متغیر `NO_PROXY` از پروکسی بیرون نگه دارید.

اگر dispatcher می‌خواهید که متغیرهای محیطی را از درون کد بخواند، کلاس `EnvHttpProxyAgent` در undici همین کار را می‌کند:

```javascript
import { fetch, EnvHttpProxyAgent } from "undici";

const res = await fetch("https://httpbin.org/ip", { dispatcher: new EnvHttpProxyAgent() });
```

## چگونه با Axios از پروکسی استفاده کنیم؟

Axios در Node.js از ماژول‌های کلاسیک `http` و `https` استفاده می‌کند و دو راه برای به کار بردن پروکسی دارد.

### گزینه proxy داخلی

گزینه `proxy` در [پیکربندی درخواست](https://axios-http.com/docs/req_config) در Axios برای آدرس‌های رمزنگاری‌نشده `http://` کار می‌کند:

```javascript
import axios from "axios";

const { data } = await axios.get("http://httpbin.org/ip", {
  proxy: {
    protocol: "http",
    host: "pr.proxynet.io",
    port: 8000,
    auth: { username: "user", password: "pass" },
  },
  timeout: 20_000,
});
console.log(data);
```

رمز درون فیلد `auth` کدگذاری نمی‌شود؛ نویسه‌های خاص را می‌توانید همان‌طور که هستند بنویسید.

### https-proxy-agent برای آدرس‌های HTTPS

وقتی آدرس مقصد HTTPS است، سپردن ساخت تونل به یک agent نتیجه قابل‌اعتمادتری می‌دهد:

```bash
npm install axios https-proxy-agent
```

```javascript
import axios from "axios";
import { HttpsProxyAgent } from "https-proxy-agent";

const httpsAgent = new HttpsProxyAgent("http://user:pass@pr.proxynet.io:8000");

const client = axios.create({
  httpsAgent,
  proxy: false, // منطق پروکسی خود Axios را خاموش می‌کند و ساخت تونل را به agent می‌سپارد
  timeout: 20_000,
});

const { status, data } = await client.get("https://httpbin.org/ip");
console.log(status, data);
```

خط `proxy: false` را از قلم نیندازید. وقتی گزینه `proxy` داده نشود، Axios ممکن است بکوشد پروکسی متغیرهای محیطی را با منطق خودش اعمال کند و این یعنی دو رفتار ناسازگار پروکسی کنار agent. بستن agent یک بار با `axios.create` شما را از تکرار آن در هر فراخوانی بی‌نیاز می‌کند.

## چگونه با node-fetch از پروکسی استفاده کنیم؟

پیش از آمدن fetch داخلی، node-fetch رایج‌ترین پیاده‌سازی fetch در Node.js بود و هنوز در پروژه‌های قدیمی زیاد دیده می‌شود. برخلاف fetch داخلی، از ماژول کلاسیک `http` استفاده می‌کند، پس پروکسی با گزینه `agent` داده می‌شود:

```bash
npm install node-fetch https-proxy-agent
```

```javascript
import fetch from "node-fetch";
import { HttpsProxyAgent } from "https-proxy-agent";

const agent = new HttpsProxyAgent("http://user:pass@pr.proxynet.io:8000");

const res = await fetch("https://httpbin.org/ip", { agent });
console.log(res.status, await res.json());
```

نسخه 3 از node-fetch فقط به‌صورت ماژول ES منتشر می‌شود؛ اگر در پروژه CommonJS که از `require` استفاده می‌کند نمی‌توانید آن را با `import` بارگذاری کنید، رفتن به fetch داخلی معمولاً کم‌زحمت‌تر است. دلیلی برای افزودن node-fetch به پروژه تازه وجود ندارد.

## چگونه از پروکسی SOCKS5 استفاده کنیم؟

`ProxyAgent` در undici برای پروکسی‌های HTTP است و fetch داخلی از SOCKS5 پشتیبانی نمی‌کند. برای کار با پروکسی SOCKS5 بسته `socks-proxy-agent` را همراه Axios یا node-fetch به کار ببرید:

```bash
npm install socks-proxy-agent
```

```javascript
import axios from "axios";
import { SocksProxyAgent } from "socks-proxy-agent";

// socks5h: نام دامنه در سمت پروکسی resolve می‌شود، پس هیچ پرس‌وجوی DNS از شبکه شما خارج نمی‌شود
const agent = new SocksProxyAgent("socks5h://user:pass@pr.proxynet.io:1080");

const { data } = await axios.get("https://httpbin.org/ip", {
  httpAgent: agent,
  httpsAgent: agent,
  proxy: false,
});
console.log(data);
```

در node-fetch همان agent به شکل `fetch(url, { agent })` داده می‌شود. در لاگ‌های پروکسی آزمون ما، درخواست‌هایی که با طرح `socks5h://` فرستاده شدند به‌صورت نام دامنه به پروکسی رسیدند، نه آدرس IP. طرح `socks5://` نام دامنه را روی رایانه شما resolve می‌کند؛ مشکلاتی که این کار ایجاد می‌کند در [نشت WebRTC و DNS](/fa/blog/webrtc-dns-leak) آمده است. سازوکار SOCKS را در [پروکسی SOCKS5: چطور کار می‌کند و چه فرقی دارد](/fa/blog/socks5-proxy-101) توضیح داده‌ایم.

## کتابخانه‌ها پروکسی را چگونه می‌گیرند؟

| کلاینت | شیوه دادن پروکسی | متغیر محیطی | SOCKS5 | خطای احراز هویت |
|---|---|---|---|---|
| fetch داخلی | `NODE_USE_ENV_PROXY` یا `--use-env-proxy` | فقط با پرچم | ندارد | `fetch failed` |
| `fetch` در undici | `dispatcher: new ProxyAgent(...)` | با `EnvHttpProxyAgent` | ندارد | `fetch failed` با علت لغو درخواست |
| Axios | گزینه `proxy` یا `httpsAgent` همراه `proxy: false` | اگر گزینه‌ای داده نشود | با `socks-proxy-agent` | خطا با کد وضعیت `407` |
| node-fetch | `agent` | ندارد | با `socks-proxy-agent` | بسته به agent |
| `http.request` | `agent` | ندارد | با `socks-proxy-agent` | بسته به agent |

ستون آخر هنگام اشکال‌زدایی مهم است. در آزمون ما با رمز نادرست، Axios علت را با پیام `Request failed with status code 407` و `error.response.status === 407` روشن نشان داد. تابع `fetch` در undici فقط خطای `fetch failed` داد و علت را «Request was cancelled» گزارش کرد؛ خود پیام از احراز هویت نامی نمی‌برد. اگر در undici `fetch failed` دیدید، نخستین چیزی که باید بررسی کنید نام کاربری و رمز پروکسی است. همه علت‌های `407` را در [احراز هویت پروکسی: نام کاربری و رمز یا لیست سفید IP](/fa/blog/proxy-authentication-methods) گرد آورده‌ایم.

## اطلاعات ورود و نویسه‌های خاص

در همه روش‌هایی که آدرس پروکسی را به شکل URL می‌گیرند (`ProxyAgent` در undici، `https-proxy-agent`، `socks-proxy-agent`، متغیرهای محیطی)، نویسه‌هایی مانند `@`، `:`، `/` و `#` در رمز باید کدگذاری شوند. در غیر این صورت آدرس نادرست تفسیر می‌شود.

```javascript
const user = process.env.PROXY_USER;
const pass = encodeURIComponent(process.env.PROXY_PASS);

const proxyUrl = `http://${user}:${pass}@pr.proxynet.io:8000`;
```

خواندن اطلاعات ورود از متغیرهای محیطی به‌جای نوشتن در کد، نمی‌گذارد رمز هر جا که کد به اشتراک گذاشته می‌شود دیده شود. در فیلد `proxy.auth` در Axios رمز بدون کدگذاری نوشته می‌شود.

## چرخش IP و تلاش دوباره

در یک کار واقعی جمع‌آوری داده، درخواست‌ها گاهی ناموفق می‌شوند: نقطه خروج پروکسی به مقصد نمی‌رسد، مقصد `429` یا `503` برمی‌گرداند یا اتصال timeout می‌شود. نمونه زیر از میان چند پروکسی تصادفی انتخاب می‌کند، درخواست ناموفق را با backoff نمایی دوباره می‌فرستد و با دسته‌های کوچک تعداد درخواست‌های هم‌زمان را محدود می‌کند:

```javascript
import { fetch, ProxyAgent } from "undici";

const PROXIES = [
  "http://user:pass@pr.proxynet.io:8000",
  "http://user:pass@pr.proxynet.io:8001",
];
const agents = PROXIES.map((p) => new ProxyAgent(p));
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));

async function getWithRetry(url, { attempts = 4, baseMs = 500 } = {}) {
  let lastError;
  for (let i = 0; i < attempts; i++) {
    const dispatcher = agents[Math.floor(Math.random() * agents.length)];
    try {
      const res = await fetch(url, { dispatcher, signal: AbortSignal.timeout(20_000) });
      if (res.status === 429 || res.status >= 500) {
        await res.body?.cancel();
        throw new Error(`HTTP ${res.status}`);
      }
      return await res.text();
    } catch (err) {
      lastError = err;
      await sleep(baseMs * 2 ** i + Math.random() * 250);
    }
  }
  throw lastError;
}

async function crawl(urls, concurrency = 5) {
  const results = [];
  for (let i = 0; i < urls.length; i += concurrency) {
    const batch = urls.slice(i, i + concurrency);
    results.push(...(await Promise.allSettled(batch.map((u) => getWithRetry(u)))));
  }
  return results;
}

const urls = ["https://httpbin.org/ip", "https://httpbin.org/status/503", "https://example.com/"];
const results = await crawl(urls, 2);
results.forEach((r, i) =>
  console.log(urls[i], r.status, r.status === "fulfilled" ? `${r.value.length} bytes` : r.reason.message),
);
```

سه جزئیات کد مهم است:

- **`Promise.allSettled`** نمی‌گذارد درخواست ناموفق در یک دسته بقیه را متوقف کند. با `Promise.all` یک `503` نتیجه کل دسته را از بین می‌برد. در نمونه، آدرس `/status/503` پس از چهار تلاش `rejected` شد و آدرس‌های دیگر نتیجه‌شان را برگرداندند.
- **`res.body?.cancel()`** اتصال پاسخی را که قرار است دوباره تلاش شود بدون خواندن بدنه آزاد می‌کند. بدنه‌های خوانده‌نشده می‌توانند مخزن اتصال را پر کنند.
- **جزء تصادفی** (`Math.random() * 250`) نمی‌گذارد درخواست‌هایی که هم‌زمان ناموفق شده‌اند هم‌زمان دوباره فرستاده شوند و انباشت تازه‌ای بسازند.

به‌جای مدیریت فهرست پروکسی به دست خودتان، اگر از [پروکسی چرخشی](https://proxynet.io/fa/rotating-proxy) استفاده کنید که از یک آدرس در هر اتصال IP خروجی متفاوتی می‌دهد، آرایه `PROXIES` یک عضو می‌شود و چرخش در سمت ارائه‌دهنده انجام می‌شود. برای کارهایی که باید در طول نشست همان IP حفظ شود (صفحه‌های نیازمند ورود، جریان‌های چندمرحله‌ای)، [پروکسی با نشست ثابت](https://proxynet.io/fa/sticky-proxy) ترجیح داده می‌شود.

این نمونه هدر `Retry-After` پاسخ `429` را نمی‌خواند. رویکردی که به هدر احترام می‌گذارد و کدهای وضعیتی را که نباید دوباره تلاش شوند جدا می‌کند در [کدهای وضعیت HTTP در وب اسکرپینگ](/fa/blog/http-status-codes-web-scraping) آمده است. اینکه مقدار همروندی در عمل چه اثری بر سرعت دارد در [همروندی و موازی‌سازی](/fa/blog/concurrency-vs-parallelism) بررسی شده است.

## چگونه از کار کردن پروکسی مطمئن شویم؟

با هر پیکربندی تازه بررسی کنید که درخواست واقعاً از پروکسی می‌گذرد. ساده‌ترین راه، فرستادن درخواست به آدرسی است که IP خروجی را برمی‌گرداند؛ یک بار بدون پروکسی و یک بار با آن:

```javascript
import { fetch, ProxyAgent } from "undici";

const ip = async (options = {}) => (await (await fetch("https://api.ipify.org?format=json", options)).json()).ip;

console.log("without proxy:", await ip());
console.log("with proxy:", await ip({ dispatcher: new ProxyAgent(process.env.HTTPS_PROXY) }));
```

اگر هر دو خط یک آدرس نشان دهند، درخواست از پروکسی نمی‌گذرد. رایج‌ترین علت، دادن `agent` به fetch داخلی یا به کار بردن agent در Axios بدون نوشتن `proxy: false` است.

## اشتباهات رایج

- **دادن `agent` به fetch داخلی.** گزینه بی‌صدا نادیده گرفته می‌شود. کلید درست در fetch، `dispatcher` است.
- **دادن `ProxyAgent` بسته npm از undici به fetch سراسری.** وقتی نسخه‌ها جور نباشند خطای `fetch failed` می‌گیرید؛ `fetch` را هم از undici وارد کنید.
- **تنظیم `HTTPS_PROXY` و فرض خواندن آن توسط fetch داخلی.** بدون `NODE_USE_ENV_PROXY` یا `--use-env-proxy` آن را نمی‌خواند.
- **ننوشتن `proxy: false` همراه agent در Axios.** دو سازوکار پروکسی با هم تداخل می‌کنند.
- **کدگذاری نکردن نویسه‌های خاص رمز.** آدرس نادرست تفسیر می‌شود و احراز هویت ناموفق است.
- **resolve محلی DNS با `socks5://`.** برای resolve از راه دور `socks5h://` را به کار ببرید.
- **تعیین نکردن timeout.** نقطه خروج پروکسی که پاسخ نمی‌دهد، درخواست بدون timeout را دقیقه‌ها معطل می‌کند. در undici از `AbortSignal.timeout` و در Axios از `timeout` استفاده کنید.
- **آغاز همه درخواست‌ها یک‌جا با `Promise.all`.** هم به مخزن اتصال خودتان و هم به محدودیت نرخ سایت مقصد فشار می‌آورد.

## کدام روش را انتخاب کنیم؟

| وضعیت شما | پیشنهاد |
|---|---|
| پروژه تازه با وابستگی کم | `fetch` در undici همراه `ProxyAgent` |
| عبور دادن اسکریپت موجود از پروکسی بدون تغییر کد | `NODE_USE_ENV_PROXY=1` همراه `HTTPS_PROXY` |
| پروژه از قبل Axios دارد | Axios همراه `https-proxy-agent` و `proxy: false` |
| پروژه قدیمی با node-fetch | node-fetch همراه `agent` |
| پروکسی SOCKS5 | Axios یا node-fetch همراه `socks-proxy-agent` و `socks5h://` |
| IP متفاوت در هر درخواست | پروکسی چرخشی، یک آدرس |
| همان IP در طول نشست | پروکسی sticky |
| پیام خطای روشن اهمیت دارد | Axios (کد 407 را با کد وضعیت نشان می‌دهد) |

هیچ‌کدام از این‌ها درباره جاوااسکریپتی که در مرورگر اجرا می‌شود صدق نمی‌کند: fetch مرورگر نمی‌تواند پروکسی را از درون کد عوض کند؛ پروکسی در تنظیمات مرورگر یا سیستم‌عامل تعیین می‌شود. برای تنظیم در ویندوز، [تنظیم پروکسی در ویندوز و کروم](/fa/blog/windows-chrome-proxy-settings) را ببینید.

## پرسش‌های متداول

### آیا fetch داخلی Node.js از پروکسی پشتیبانی می‌کند؟

از Node.js 22.21.0 و 24.5.0، وقتی متغیر محیطی `NODE_USE_ENV_PROXY=1` یا گزینه `--use-env-proxy` به کار رود، متغیرهای `HTTP_PROXY` و `HTTPS_PROXY` را می‌خواند. برای تعیین پروکسی به تفکیک درخواست از درون کد، `fetch` و `ProxyAgent` از undici را به کار ببرید.

### آیا Axios متغیر محیطی HTTPS_PROXY را می‌خواند؟

در Node.js وقتی گزینه `proxy` داده نشود، Axios می‌کوشد پروکسی متغیرهای محیطی را به کار ببرد. برای رفتاری روشن و قابل پیش‌بینی، پیشنهاد می‌کنیم پروکسی را با agent تعریف کنید و `proxy: false` بنویسید.

### آیا می‌توانم برای هر درخواست پروکسی متفاوتی به کار ببرم؟

بله. در undici می‌توانید به هر فراخوانی `fetch` یک `ProxyAgent` متفاوت و در Axios یک `httpsAgent` متفاوت بدهید. به‌جای ساختن agent در هر درخواست، مانند نمونه بالا یک بار بسازید و دوباره به کار ببرید؛ هر agent تازه مخزن اتصال خودش را باز می‌کند.

### هنگام استفاده از پروکسی، کوکی‌ها چگونه حفظ می‌شوند؟

fetch داخلی و undici کوکی نگه نمی‌دارند؛ باید هدر `Set-Cookie` را بخوانید و در درخواست بعدی به‌صورت هدر `Cookie` بیفزایید. در Axios می‌توانید از cookie jar مبتنی بر `tough-cookie` استفاده کنید. به یاد داشته باشید که همراه کوکی‌ها، آدرس IP هم باید در سراسر نشست ثابت بماند.

### در Puppeteer یا Playwright پروکسی چگونه داده می‌شود؟

ابزارهای خودکارسازی مرورگر پروکسی را مانند کتابخانه‌های Node.js نمی‌گیرند؛ آن را به‌صورت گزینه هنگام اجرای مرورگر دریافت می‌کنند. agentهای این نوشته روی مرورگر اثری ندارند.

### جاوااسکریپت را انتخاب کنم یا پایتون؟

پروکسی در هر دو زبان کار می‌کند؛ در پایتون بیشتر کتابخانه‌ها پروکسی را با یک پارامتر می‌گیرند، در حالی که در Node.js سازوکار با کتابخانه تغییر می‌کند. انتخاب معمولاً به زبان تیم و ساختار صفحه‌های مقصد بستگی دارد.

## خلاصه

در Node.js پروکسی بسته به کلاینت به سه شکل داده می‌شود: `dispatcher` در undici یا `NODE_USE_ENV_PROXY` برای fetch داخلی، و `agent` برای Axios و node-fetch. برای مقصدهای HTTPS، Axios را با `https-proxy-agent` و `proxy: false`، و SOCKS5 را با `socks-proxy-agent` و طرح `socks5h://` به کار ببرید. `ProxyAgent` و `fetch` را از یک بسته بردارید، رمز را کدگذاری کنید، timeout تعیین کنید و درخواست‌ها را در دسته‌های کوچک `Promise.allSettled` همراه منطق تلاش دوباره اجرا کنید. پلن‌های مناسب کار جمع‌آوری داده را در صفحه [راه‌حل استخراج داده](/fa/data-scraping) می‌یابید.
