---
title: "معادل cURL در JavaScript: fetch، Axios و پروکسی"
description: "معادل دستورهای cURL در JavaScript، fetch و Axios است. تنظیم هدر، بدنه، احراز هویت و پروکسی در Node.js را با نمونه‌کدهای آزموده‌شده توضیح می‌دهیم."
url: https://proxynet.io/fa/blog/curl-in-javascript
date: 2026-09-13
author: "Acar Diveroli"
category: "آموزش‌ها"
lang: fa
---

# معادل cURL در JavaScript: fetch، Axios و پروکسی

مستندات API و ابزارهای توسعه‌دهنده مرورگر اغلب درخواست نمونه را به شکل یک **دستور cURL** می‌دهند. برای یک آزمایش سریع در ترمینال ایده‌آل است؛ اما وقتی همان درخواست را باید به یک اپلیکیشن Node.js یا اسکریپت اسکرپینگ منتقل کنید، لازم است دستور را به JavaScript تبدیل کنید. در این نوشته معادل‌های JavaScript پرکاربردترین گزینه‌های cURL، نمونه‌های تبدیل، چهار روش استفاده از پروکسی در Node.js، مدیریت خطا و اشتباهات رایج را توضیح می‌دهیم.

همه نمونه‌ها روی Node.js 24 با undici 8 و Axios 1.20 آزموده شده‌اند.

> **نکته: پاسخ کوتاه**
>
> معادل دستور `curl URL`، `fetch(url)` یا `axios.get(url)` است؛ هدرهای `-H` به شیء `headers`، بدنه `-d` به `body`/پارامتر دوم و `-x proxy` در Node.js به `ProxyAgent` در undici یا عامل `https-proxy-agent` برای Axios تبدیل می‌شود. در JavaScript سمت مرورگر، پروکسی از راه کد قابل تعریف نیست.

## معادل cURL در JavaScript چیست؟

دو گزینه اصلی وجود دارد:

- **fetch:** در مرورگرها و از Node.js 18 به بعد به‌صورت درون‌ساخت موجود است. نیازی به بسته اضافه ندارد. پیاده‌سازی fetch در Node.js در پس‌زمینه از کتابخانه [undici](https://undici.nodejs.org/) استفاده می‌کند.
- **Axios:** کتابخانه‌ای محبوب و دیرینه که تبدیل خودکار JSON را انجام می‌دهد و پشتیبانی درخواست و پاسخ میانگیر (interceptor) ارائه می‌دهد.

استفاده دوباره از یک دستور cURL بدون خروج از ترمینال هم ممکن است (با `child_process`)، اما این روش مدیریت خطا و قابلیت انتقال را دشوار می‌کند؛ به نصب بودن cURL روی دستگاه وابسته می‌مانید. نوشتن با یک کلاینت بومی تقریباً همیشه بهتر است.

## معادل‌های JavaScript گزینه‌های cURL

| cURL | fetch | Axios |
|---|---|---|
| `curl URL` | `fetch(url)` | `axios.get(url)` |
| `-X POST` | `method: "POST"` | `axios.post(url, veri)` |
| `-H "Ad: Değer"` | `headers: { Ad: "Değer" }` | `headers: { Ad: "Değer" }` |
| `-d '{"a":1}'` | `body: JSON.stringify({ a: 1 })` | به‌عنوان پارامتر دوم، یک شیء |
| `-d "a=1&b=2"` | `body: new URLSearchParams({ a: 1, b: 2 })` | `new URLSearchParams(...)` به‌عنوان پارامتر دوم |
| `-F "dosya=@a.png"` | `body: FormData` | `FormData` به‌عنوان پارامتر دوم |
| `-u kullanici:parola` | هدر `Authorization: "Basic ..."` | `auth: { username, password }` |
| `-b "ad=deger"` (کوکی) | `headers: { Cookie: "ad=deger" }` | `headers: { Cookie: "ad=deger" }` |
| `-A "UA"` | `headers: { "User-Agent": "UA" }` | `headers: { "User-Agent": "UA" }` |
| `-L` (پیگیری تغییرمسیر) | به‌طور پیش‌فرض پیگیری می‌کند | به‌طور پیش‌فرض پیگیری می‌کند |
| `-x proxy` | `dispatcher: new ProxyAgent(...)` | `httpsAgent` یا `proxy` |
| `-m 20` (زمان پایان) | `signal: AbortSignal.timeout(20000)` | `timeout: 20000` |
| `-i` (هدرهای پاسخ) | `response.headers` | `response.headers` |
| `-o dosya` | بدنه را با `fs.writeFile` بنویسید | `responseType: "stream"` |

## نمونه: تبدیل یک درخواست POST

این دستور cURL را در نظر بگیرید:

```bash
curl -X POST https://httpbin.org/post \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer TOKEN" \
  -d '{"q": 1}'
```

### با fetch

```javascript
const response = await fetch("https://httpbin.org/post", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    Authorization: "Bearer TOKEN",
  },
  body: JSON.stringify({ q: 1 }),
  signal: AbortSignal.timeout(20000),
});

if (!response.ok) throw new Error(`HTTP ${response.status}`);
const data = await response.json();
console.log(data.json);
```

fetch ظرافتی دارد: وقتی سرور `404` یا `500` برمی‌گرداند **خطا پرتاب نمی‌کند**. باید خودتان موفق بودن پاسخ را با `response.ok` بررسی کنید. اما خطای شبکه (DNS، رد اتصال، پایان زمان) به‌صورت استثنا می‌آید.

### با Axios

```bash
npm install axios
```

```javascript
import axios from "axios";

const { data } = await axios.post(
  "https://httpbin.org/post",
  { q: 1 },
  { headers: { Authorization: "Bearer TOKEN" }, timeout: 20000 },
);

console.log(data.json);
```

Axios خودش شیء را به JSON تبدیل می‌کند، هدر `Content-Type` را اضافه می‌کند و در پاسخ‌های خارج از محدوده `2xx` خطا پرتاب می‌کند.

## نمونه: ارسال فرم و بارگذاری فایل

ارسال فرمی که در cURL به شکل `-d "a=1&b=2"` است، در JavaScript با `URLSearchParams` انجام می‌شود:

```javascript
const response = await fetch("https://httpbin.org/post", {
  method: "POST",
  body: new URLSearchParams({ a: "1", b: "2" }),
});
console.log((await response.json()).form);
```

وقتی بدنه `URLSearchParams` داده شود، fetch خودش هدر `Content-Type` را برابر `application/x-www-form-urlencoded` قرار می‌دهد. برای بارگذاری فایل (`-F`) از `FormData` استفاده می‌شود و مقدار مرز (boundary) هم خودکار اضافه می‌شود. یک نکته ظریف: اگر تابع `fetch` را از بسته undici می‌گیرید، کلاس `FormData` را هم از همان بسته بگیرید؛ `FormData` درون‌ساخت با `fetch` مربوط به undici هم‌خوان نیست و بدنه به‌صورت متن ساده ارسال می‌شود.

```javascript
import { openAsBlob } from "node:fs";

const form = new FormData();
form.append("dosya", await openAsBlob("./a.png"), "a.png");

const response = await fetch("https://httpbin.org/post", { method: "POST", body: form });
console.log(Object.keys((await response.json()).files));
```

## چهار روش استفاده از پروکسی در Node.js

در cURL، پروکسی فقط یک گزینه `-x` است. اما در Node.js روش بسته به اینکه کدام کلاینت را استفاده می‌کنید فرق دارد.

### 1. fetch و undici ProxyAgent

```bash
npm install undici
```

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

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

const response = await fetch("https://httpbin.org/ip", { dispatcher });
console.log(await response.text());
```

توجه کنید که تابع `fetch` را هم از بسته undici درون‌ریزی کرده‌ایم. fetch درون‌ساخت Node.js هم بر پایه undici است، اما چون در بسته جداگانه‌ای که نصب می‌شود ممکن است تفاوت نسخه وجود داشته باشد، گرفتن هر دو از یک بسته امن‌ترین راه است.

### 2. تنظیم عمومی برای همه فراخوانی‌های fetch

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

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

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

const response = await fetch("https://httpbin.org/ip");
console.log(await response.text());
```

این روش فراخوانی‌های fetch را که از درون یک کتابخانه شخص ثالث انجام می‌شوند هم پوشش می‌دهد؛ بدون دست زدن به کد منبع کتابخانه، ترافیک آن را از پروکسی عبور می‌دهید.

### 3. با متغیر محیطی، بدون تغییر کد

نسخه‌های جدید Node.js وقتی متغیر `NODE_USE_ENV_PROXY` فعال باشد، می‌توانند متغیرهای محیطی استاندارد پروکسی را برای fetch درون‌ساخت بخوانند:

```bash
NODE_USE_ENV_PROXY=1 HTTPS_PROXY="http://kullanici:parola@pr.proxynet.io:8000" node uygulama.mjs
```

این روش برای عبور دادن یک اسکریپت موجود از پروکسی بدون دست زدن به کد منبع مفید است. متغیر `NO_PROXY` هم خوانده می‌شود؛ با افزودن آدرس‌های شبکه داخلی به این فهرست می‌توانید آن‌ها را خارج از پروکسی نگه دارید. اینکه این ویژگی در نسخه شما هست یا نه را از [مستندات Node.js](https://nodejs.org/api/cli.html) بررسی کنید.

### 4. Axios و مقصدهای HTTPS

گزینه درون‌ساخت `proxy` در Axios، برای آدرس‌های HTTP بدون رمزنگاری بی‌دردسر کار می‌کند:

```javascript
const { data } = await axios.get("http://httpbin.org/ip", {
  proxy: {
    protocol: "http",
    host: "pr.proxynet.io",
    port: 8000,
    auth: { username: "kullanici", password: "parola" },
  },
});
```

برای آدرس‌های HTTPS اما استفاده از یک عامل پروکسی قابل‌اعتمادتر است:

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

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

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

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

خط `proxy: false` مهم است؛ منطق داخلی پروکسی Axios را خاموش می‌کند و کل تونل را به عامل واگذار می‌کند. اگر عامل را یک‌بار بسازید و با `axios.create({ httpsAgent, proxy: false })` به یک نمونه متصل کنید، لازم نیست در هر فراخوانی دوباره بنویسید.

> **راهنمایی**
>
> حتی اگر آدرس پروکسی با `http://` شروع شود، می‌توانید با اطمینان به سایت‌های HTTPS بروید. با پروکسی یک تونل روی HTTP برپا می‌شود و ترافیک HTTPS سایت به‌صورت رمزگذاری‌شده درون همان تونل جابه‌جا می‌شود. جزئیات این تفاوت را در [تفاوت SOCKS و HTTP Proxy](/fa/blog/socks-vs-http-proxy) نوشته‌ایم.

## مقایسه چهار روش

| روش | دامنه | تغییر کد | مناسب چه حالتی |
|---|---|---|---|
| undici `ProxyAgent` | یک فراخوانی | `dispatcher` در هر فراخوانی | پروکسی متفاوت برای درخواست‌های متفاوت |
| `setGlobalDispatcher` | همه فراخوانی‌های fetch | یک خط، در ابتدا | یک پروکسی برای کل اپلیکیشن |
| `NODE_USE_ENV_PROXY` | همه فراخوانی‌های fetch درون‌ساخت | ندارد | اسکریپت موجود، محیط استقرار |
| Axios + عامل | نمونه Axios | `httpsAgent` + `proxy: false` | اگر پروژه از Axios استفاده می‌کند |

## تلاش مجدد و هم‌زمانی

در یک اسکریپت اسکرپینگ واقعی، درخواست‌ها گاهی شکست می‌خورند؛ ممکن است پروکسی به مقصد نرسد یا سایت `429` برگرداند. تابع کمکی زیر، درخواست ناموفق را با تأخیر نمایی دوباره تلاش می‌کند و شمار درخواست‌های باز هم‌زمان را محدود می‌کند:

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

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

async function getir(url, deneme = 3) {
  for (let i = 0; i < deneme; i++) {
    try {
      const r = await fetch(url, { dispatcher, signal: AbortSignal.timeout(20000) });
      if (r.status === 429 || r.status >= 500) throw new Error(`HTTP ${r.status}`);
      return await r.text();
    } catch (hata) {
      if (i === deneme - 1) throw hata;
      await new Promise((coz) => setTimeout(coz, 1000 * 2 ** i));
    }
  }
}

async function topluGetir(urls, esZamanli = 5) {
  const sonuclar = [];
  for (let i = 0; i < urls.length; i += esZamanli) {
    const grup = urls.slice(i, i + esZamanli);
    sonuclar.push(...(await Promise.allSettled(grup.map(getir))));
  }
  return sonuclar;
}

const urls = Array.from({ length: 20 }, (_, i) => `https://httpbin.org/get?i=${i}`);
const sonuclar = await topluGetir(urls);
console.log(sonuclar.filter((s) => s.status === "fulfilled").length, "başarılı");
```

`Promise.allSettled` مانع از این می‌شود که خطای یک درخواست باعث سقوط کل گروه شود؛ می‌توانید هر نتیجه را تک‌تک بررسی کنید. مدت انتظار در هر تلاش دو برابر می‌شود؛ اصرار با فاصله ثابت باعث سخت‌گیرتر شدن سایتی می‌شود که حد سرعت اعمال می‌کند.

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

### کاراکتر خاص در رمز عبور

اگر در رمز عبور پروکسی شما کاراکترهایی مانند `@`، `:` یا `/` وجود دارد، آن‌ها را در آدرس با `encodeURIComponent` کدگذاری کنید. در غیر این صورت آدرس اشتباه تجزیه می‌شود و خطای `407 Proxy Authentication Required` می‌گیرید.

### درخواست‌های بدون زمان پایان

در تنظیمات پیش‌فرض یک درخواست ممکن است مدت طولانی منتظر پاسخ بماند و اسکریپت شما گیر کند. با `AbortSignal.timeout` در fetch و `timeout` در Axios، برای هر درخواست محدودیت زمانی بگذارید.

### درخواست‌های زیاد به‌طور هم‌زمان

شروع صدها درخواست به‌طور همزمان با `Promise.all` هم محدودیت اتصال خودتان را زیر فشار می‌گذارد و هم باعث می‌شود در سایت مقصد به حد سرعت بخورید. هم‌زمانی را مانند بالا در گروه‌های کوچک محدود کنید. در کارهایی که تعداد زیادی درخواست ارسال می‌کنید، [پروکسی چرخشی](https://proxynet.io/fa/rotating-proxy) با پخش ترافیک میان IPهای مختلف ریسک مسدود شدن را کاهش می‌دهد.

### دادن `agent` به fetch درون‌ساخت

در API قدیمی `http.request` در Node.js، پروکسی با گزینه `agent` داده می‌شود. fetch درون‌ساخت این گزینه را نمی‌شناسد و آن را بی‌سروصدا نادیده می‌گیرد؛ درخواست بدون پروکسی می‌رود. کلید درست برای fetch، `dispatcher` است.

### کپی کردن هدرهای مرورگر بدون تغییر

درخواست‌های کپی‌شده از ابزارهای توسعه‌دهنده، هدرهای مخصوص مرورگر مانند `sec-ch-ua`، `sec-fetch-*` را حمل می‌کنند. در Node.js نیازی به ارسال آن‌ها نیست و برخی از آن‌ها ممکن است در سایت مقصد به‌عنوان ناسازگاری ارزیابی شوند؛ فقط هدرهایی را نگه دارید که واقعاً لازم‌اند.

### صفحاتی که درخواست HTTP برایشان کافی نیست

fetch و Axios فقط HTML‌ای را می‌گیرند که سرور برمی‌گرداند. اگر محتوا بعداً با JavaScript در مرورگر بارگذاری می‌شود، آنچه دنبالش هستید را در صفحه پیدا نمی‌کنید. در این حالت یا باید درخواست API پس‌زمینه را پیدا کنید یا از یک اتوماسیون مرورگر استفاده کنید. گزینه‌ها را در [اسکرپینگ وب: جاوااسکریپت یا پایتون؟](/fa/blog/web-scraping-javascript-vs-python) مقایسه کردیم؛ استفاده از پروکسی با Puppeteer را در [Puppeteer و CAPTCHA](/fa/blog/puppeteer-captcha) نشان دادیم.

## fetch یا Axios؟

- **fetch** را انتخاب کنید: اگر وابستگی اضافه نمی‌خواهید، کد باید هم در مرورگر و هم در Node.js اجرا شود، یا می‌خواهید از ویژگی‌های مدیریت اتصال undici بهره ببرید.
- **Axios** را انتخاب کنید: اگر به راحتی‌هایی مانند تبدیل خودکار JSON، interceptorها و پرتاب خطا در پاسخ‌های خارج از `2xx` نیاز دارید یا از قبل در پروژه استفاده می‌شود.

تفاوت میان این دو بیشتر به عادت مربوط است تا کارکرد. شروع یک پروژه جدید با fetch، تعداد وابستگی‌ها را پایین نگه می‌دارد؛ در یک پروژه بزرگ Axios هم دلیلی برای رفتن به fetch وجود ندارد.

## سؤالات متداول

### آیا می‌توانم دستور cURL را خودکار به JavaScript تبدیل کنم؟

در ابزارهای توسعه‌دهنده مرورگر، از تب Network می‌توانید روی یک درخواست راست‌کلیک کنید و با گزینه «Copy as fetch» مستقیماً آن را به‌صورت کد fetch کپی کنید. با این حال کد به‌دست‌آمده را بازبینی کنید؛ هدرهای مخصوص مرورگر ممکن است در Node.js غیرضروری باشند. اگر همین دستور را به Python منتقل می‌کنید، معادل گزینه‌های cURL در `json=`، `data=` و `params=` را در مقاله [ارسال JSON با POST در Python Requests: معادل‌های cURL](/fa/blog/python-requests-post-json) به‌صورت جدول آورده‌ایم.

### آیا می‌توانم در Node.js از پروکسی SOCKS5 استفاده کنم؟

fetch درون‌ساخت و undici ProxyAgent برای پروکسی HTTP هستند. برای SOCKS5 باید با بسته‌ای اضافه مانند `socks-proxy-agent` عامل تعریف کنید. در سمت cURL، شمای `socks5h://` مستقیماً پشتیبانی می‌شود؛ جزئیات در [چگونه با cURL از پروکسی استفاده کنیم؟](/fa/blog/curl-proxy).

### آیا در JavaScript سمت مرورگر می‌توان پروکسی تعریف کرد؟

خیر. fetch در مرورگر اجازه نمی‌دهد تنظیم پروکسی را از راه کد تغییر دهید؛ پروکسی در تنظیمات مرورگر یا سیستم‌عامل تعریف می‌شود. مدیریت پروکسی از درون کد مخصوص محیط‌های سروری مانند Node.js است. برای پروکسی در سطح مرورگر از افزونه‌هایی مانند [SwitchyOmega](/fa/blog/switchy-omega) استفاده می‌شود.

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

fetch درون‌ساخت کوکی ذخیره نمی‌کند. باید هدر `Set-Cookie` را از پاسخ بخوانید و به‌عنوان هدر `Cookie` به درخواست بعدی اضافه کنید؛ یا با Axios از یک ظرف کوکی مبتنی بر `tough-cookie` استفاده کنید. فراموش نکنید که در جریان‌های ورود، IP هم باید ثابت بماند؛ [پروکسی با نشست ثابت](https://proxynet.io/fa/sticky-proxy) برای همین کار طراحی شده است.

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

بله. با undici می‌توانید به هر فراخوانی یک `ProxyAgent` متفاوت بدهید. اما به‌جای مدیریت خودتان فهرست، استفاده از پروکسی چرخشی ساده‌تر است: یک آدرس، در هر اتصال IP خروجی متفاوت.

### آیا همین کد در TypeScript کار می‌کند؟

بله. undici و Axios با تعریف‌های تایپ عرضه می‌شوند؛ برای گزینه `dispatcher` باید از نوع `fetch` خود undici استفاده کنید، چون تعریف تایپ fetch درون‌ساخت این گزینه را نمی‌شناسد.

## خلاصه

دستورهای cURL در JavaScript دقیقاً با fetch یا Axios قابل جایگزینی هستند. برای پروکسی در Node.js چهار روش وجود دارد: undici ProxyAgent، `dispatcher` عمومی، متغیر محیطی `NODE_USE_ENV_PROXY` و عامل پروکسی برای Axios. افزودن زمان پایان، بررسی خطا، تلاش مجدد با تأخیر نمایی و محدودیت هم‌زمانی از همان ابتدا، اسکریپت‌های شما را بسیار قابل‌اعتمادتر می‌کند. بسته‌های مناسب برای ترافیک وب را در صفحه [پروکسی HTTPS](https://proxynet.io/fa/https-proxy) ما پیدا می‌کنید.
