---
title: "cURL em JavaScript: fetch, Axios e proxy"
description: "O equivalente dos comandos cURL em JavaScript é fetch e Axios. Explicamos cabeçalho, corpo, autenticação e proxy no Node.js com exemplos de código testados."
url: https://proxynet.io/pt-br/blog/curl-in-javascript
date: 2026-09-13
author: "Acar Diveroli"
category: "Tutoriais"
lang: pt-BR
---

# cURL em JavaScript: fetch, Axios e proxy

Documentações de API e as ferramentas de desenvolvedor do navegador costumam apresentar a requisição de exemplo como um **comando cURL**. É ideal para um teste rápido no terminal; mas quando você precisa levar a mesma requisição para uma aplicação Node.js ou para um script de coleta de dados, precisa converter o comando para JavaScript. Neste artigo explicamos os equivalentes em JavaScript das opções mais usadas do cURL, exemplos de conversão, quatro formas de usar proxy no Node.js, tratamento de erros e os erros mais comuns.

Todos os exemplos foram testados no Node.js 24, com undici 8 e Axios 1.20.

> **Nota: Resposta rápida**
>
> O equivalente do comando `curl URL` é `fetch(url)` ou `axios.get(url)`; os cabeçalhos `-H` viram o objeto `headers`, o corpo `-d` vira `body`/o segundo parâmetro, e `-x proxy` vira o `ProxyAgent` do undici no Node.js ou o agente `https-proxy-agent` no caso do Axios. Em JavaScript rodando no navegador, o proxy não pode ser definido por código.

## Qual é o equivalente do cURL em JavaScript?

Existem duas opções principais:

- **fetch:** vem embutido nos navegadores e, desde o Node.js 18, também no Node.js. Não exige pacote adicional. A implementação de fetch do Node.js usa a biblioteca [undici](https://undici.nodejs.org/) por baixo dos panos.
- **Axios:** biblioteca popular, usada há muito tempo, que converte JSON automaticamente e oferece suporte a interceptadores de requisição e resposta.

Também é possível reutilizar um comando cURL sem sair do terminal (via `child_process`), mas esse método dificulta o tratamento de erros e a portabilidade; você fica dependente de o cURL estar instalado na máquina. Escrever com um cliente nativo é quase sempre melhor.

## Equivalentes em JavaScript das opções do cURL

| cURL | fetch | Axios |
|---|---|---|
| `curl URL` | `fetch(url)` | `axios.get(url)` |
| `-X POST` | `method: "POST"` | `axios.post(url, dados)` |
| `-H "Nome: Valor"` | `headers: { Nome: "Valor" }` | `headers: { Nome: "Valor" }` |
| `-d '{"a":1}'` | `body: JSON.stringify({ a: 1 })` | objeto como segundo parâmetro |
| `-d "a=1&b=2"` | `body: new URLSearchParams({ a: 1, b: 2 })` | `new URLSearchParams(...)` como segundo parâmetro |
| `-F "arquivo=@a.png"` | `body: FormData` | `FormData` como segundo parâmetro |
| `-u usuario:senha` | cabeçalho `Authorization: "Basic ..."` | `auth: { username, password }` |
| `-b "nome=valor"` (cookie) | `headers: { Cookie: "nome=valor" }` | `headers: { Cookie: "nome=valor" }` |
| `-A "UA"` | `headers: { "User-Agent": "UA" }` | `headers: { "User-Agent": "UA" }` |
| `-L` (segue redirecionamento) | Segue por padrão | Segue por padrão |
| `-x proxy` | `dispatcher: new ProxyAgent(...)` | `httpsAgent` ou `proxy` |
| `-m 20` (tempo limite) | `signal: AbortSignal.timeout(20000)` | `timeout: 20000` |
| `-i` (cabeçalhos de resposta) | `response.headers` | `response.headers` |
| `-o arquivo` | escreva o corpo com `fs.writeFile` | `responseType: "stream"` |

## Exemplo: convertendo uma requisição POST

Vamos considerar o seguinte comando cURL:

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

### Com 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);
```

O fetch tem uma particularidade: quando o servidor retorna 404 ou 500, ele **não lança erro**. Você mesmo precisa checar se a resposta foi bem-sucedida usando `response.ok`. Já um erro de rede (DNS, conexão recusada, tempo limite) chega como exceção.

### Com 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);
```

O Axios converte o objeto para JSON automaticamente, adiciona o cabeçalho `Content-Type` e lança erro em respostas fora da faixa 2xx.

## Exemplo: envio de formulário e upload de arquivo

Um envio de formulário no formato `-d "a=1&b=2"` do cURL é atendido em JavaScript com `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);
```

Quando um corpo `URLSearchParams` é passado, o fetch define sozinho o cabeçalho `Content-Type` como `application/x-www-form-urlencoded`. Para upload de arquivo (`-F`), usa-se `FormData`, e o valor de fronteira (boundary) também é adicionado automaticamente. Um detalhe: se você importa a função `fetch` do pacote undici, importe também a classe `FormData` do mesmo pacote; o `FormData` embutido não combina com o `fetch` do undici, e o corpo vai como texto puro.

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

const form = new FormData();
form.append("arquivo", 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));
```

## Quatro formas de usar proxy no Node.js

No cURL, o proxy é uma única opção, `-x`. No Node.js, o método muda de acordo com o cliente que você usa.

### 1. fetch e o ProxyAgent do undici

```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());
```

Note que também importamos a função `fetch` do pacote undici. O fetch embutido do Node.js também é baseado no undici, mas, como pode haver diferença de versão no pacote instalado separadamente, importar os dois do mesmo pacote é o caminho mais seguro.

### 2. Configuração global para todas as chamadas fetch

Se você quer que toda chamada fetch da aplicação use o mesmo proxy, pode definir um dispatcher global:

```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());
```

Esse método também cobre chamadas fetch feitas dentro de uma biblioteca de terceiros; você passa o tráfego dela pelo proxy sem tocar no código-fonte da biblioteca.

### 3. Por variável de ambiente, sem alterar código

Versões recentes do Node.js conseguem ler as variáveis de ambiente padrão de proxy para o fetch embutido quando a variável `NODE_USE_ENV_PROXY` está ativada:

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

Esse método é útil para passar um script já existente pelo proxy sem tocar no código-fonte. A variável `NO_PROXY` também é lida; você pode adicionar endereços de rede interna a essa lista para mantê-los fora do proxy. Verifique na [documentação do Node.js](https://nodejs.org/api/cli.html) se esse recurso está disponível na sua versão.

### 4. Axios e destinos HTTPS

A opção `proxy` embutida do Axios funciona sem problemas para endereços HTTP sem criptografia:

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

Para endereços HTTPS, é mais confiável usar um agente de proxy:

```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);
```

A linha `proxy: false` é importante; ela desliga a própria lógica de proxy do Axios e deixa o túnel totalmente a cargo do agente. Se você criar o agente uma vez e vinculá-lo a uma instância com `axios.create({ httpsAgent, proxy: false })`, não precisa reescrevê-lo em cada chamada.

> **Dica**
>
> Mesmo que o endereço do proxy comece com `http://`, você pode acessar sites HTTPS com segurança. Um túnel é criado com o proxy via HTTP, e o tráfego HTTPS do site é transportado de forma criptografada dentro desse túnel. Os detalhes das diferenças estão no artigo [Diferença entre SOCKS e HTTP proxy](/pt-br/blog/socks-vs-http-proxy).

## Comparando os quatro métodos

| Método | Escopo | Alteração de código | Situação em que é indicado |
|---|---|---|---|
| `ProxyAgent` do undici | Uma única chamada | `dispatcher` em cada chamada | Proxy diferente para requisições diferentes |
| `setGlobalDispatcher` | Todas as chamadas fetch | Uma linha, no início | Um único proxy para toda a aplicação |
| `NODE_USE_ENV_PROXY` | Todas as chamadas do fetch embutido | Nenhuma | Script existente, ambiente de implantação |
| Axios + agente | Instância do Axios | `httpsAgent` + `proxy: false` | Quando o projeto já usa Axios |

## Nova tentativa e concorrência

Em um script real de coleta de dados, as requisições às vezes falham; o proxy pode não alcançar o destino, ou o site pode retornar 429. A função auxiliar abaixo tenta novamente a requisição com falha usando espera exponencial e limita o número de requisições abertas ao mesmo tempo:

```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, "com sucesso");
```

O `Promise.allSettled` evita que o erro de uma requisição derrube todo o grupo; você pode examinar cada resultado individualmente. O tempo de espera dobra a cada tentativa; insistir em intervalos fixos pode fazer um site com limite de taxa aplicar restrições ainda mais rígidas.

## Erros comuns

### Caractere especial na senha

Se a sua senha de proxy tiver caracteres como `@`, `:` ou `/`, codifique-os dentro do endereço com `encodeURIComponent`. Caso contrário, o endereço é interpretado errado e você recebe o erro "407 Proxy Authentication Required".

### Requisições sem tempo limite

Nas configurações padrão, uma requisição pode esperar resposta por muito tempo e travar o seu script. Coloque um limite de tempo em cada requisição com `AbortSignal.timeout` no fetch e `timeout` no Axios.

### Muitas requisições ao mesmo tempo

Disparar centenas de requisições de uma vez com `Promise.all` sobrecarrega tanto os seus próprios limites de conexão quanto faz você esbarrar em limite de taxa no site de destino. Limite a concorrência em pequenos grupos, como no exemplo acima. Em trabalhos com muitas requisições, o [Proxies rotativos](https://proxynet.io/pt-br/rotating-proxy) distribui o tráfego entre IPs diferentes e reduz o risco de bloqueio.

### Passar `agent` para o fetch embutido

Na antiga API `http.request` do Node.js, o proxy é passado pela opção `agent`. O fetch embutido não reconhece essa opção e a ignora silenciosamente; a requisição sai sem proxy. Para o fetch, a chave correta é `dispatcher`.

### Copiar cabeçalhos do navegador tal como estão

Requisições copiadas das ferramentas de desenvolvedor carregam cabeçalhos específicos do navegador, como `sec-ch-ua` e `sec-fetch-*`. No Node.js não é necessário enviá-los, e alguns podem ser avaliados como uma inconsistência pelo site de destino; deixe apenas os cabeçalhos realmente necessários.

### Páginas em que a requisição HTTP não basta

O fetch e o Axios só obtêm o HTML retornado pelo servidor. Se o conteúdo é carregado depois, no navegador, com JavaScript, você não vai encontrar o que procura na página. Nesse caso, você precisa encontrar a requisição de API que roda em segundo plano ou usar uma automação de navegador. Comparamos as opções no artigo [Extração de dados: JavaScript ou Python?](/pt-br/blog/web-scraping-javascript-vs-python); mostramos o uso de proxy com o Puppeteer no artigo [Puppeteer e CAPTCHA](/pt-br/blog/puppeteer-captcha).

## fetch ou Axios?

- **Escolha fetch** se você não quer uma dependência adicional, se o código vai rodar tanto no navegador quanto no Node.js, ou se quer aproveitar os recursos de gerenciamento de conexão do undici.
- **Escolha Axios** se você precisa de conveniências como conversão automática de JSON, interceptadores e erro automático em respostas fora do 2xx, ou se o projeto já o usa.

A diferença entre os dois está mais no hábito do que na função. Começar um projeto novo com fetch mantém o número de dependências baixo; em um projeto grande já feito com Axios, não há motivo para migrar para o fetch.

## Perguntas frequentes

### Posso converter um comando cURL para JavaScript automaticamente?

Nas ferramentas de desenvolvedor do navegador, na aba Rede, você pode clicar com o botão direito em uma requisição e usar a opção "Copy as fetch" para copiar diretamente como código fetch. Ainda assim, revise o código gerado; cabeçalhos específicos do navegador podem ser desnecessários no Node.js. Se você vai levar o mesmo comando para o Python, reunimos em uma tabela os equivalentes das opções do cURL em `json=`, `data=` e `params=` no artigo [POST com JSON no Python Requests: equivalentes do cURL](/pt-br/blog/python-requests-post-json).

### Posso usar proxy SOCKS5 no Node.js?

O fetch embutido e o ProxyAgent do undici são para proxy HTTP. Para SOCKS5, você precisa definir um agente com um pacote adicional, como `socks-proxy-agent`. No lado do cURL, o esquema `socks5h://` já é suportado diretamente; os detalhes estão no artigo [Como usar proxy com o cURL?](/pt-br/blog/curl-proxy).

### Dá para definir proxy em JavaScript rodando no navegador?

Não. O fetch do navegador não permite alterar a configuração de proxy por código; o proxy é definido nas configurações do navegador ou do sistema operacional. Gerenciar o proxy a partir do código é algo específico de ambientes de servidor, como o Node.js. Para proxy no nível do navegador, são usadas extensões como o [SwitchyOmega](/pt-br/blog/switchy-omega).

### Como mantenho cookies entre requisições?

O fetch embutido não guarda cookies. Você precisa ler o cabeçalho `Set-Cookie` da resposta e adicioná-lo como cabeçalho `Cookie` na requisição seguinte; ou pode usar um cookie jar baseado em `tough-cookie` com o Axios. Não esqueça que, em fluxos com login, o IP também precisa se manter fixo; o [Proxies de sessão fixa](https://proxynet.io/pt-br/sticky-proxy) foi feito para isso.

### Posso usar um proxy diferente em cada requisição?

Sim. Com o undici, você pode passar um `ProxyAgent` diferente em cada chamada. Mas, em vez de gerenciar a lista você mesmo, usar um proxy rotativo é mais simples: um único endereço, um IP de saída diferente em cada conexão.

### O mesmo código funciona em TypeScript?

Sim. O undici e o Axios vêm com definições de tipo; para a opção `dispatcher`, é preciso usar o próprio tipo `fetch` do undici, porque a definição de tipo do fetch embutido não conhece essa opção.

## Em resumo

Comandos cURL podem ser atendidos em JavaScript, ponto a ponto, com fetch ou Axios. No Node.js, existem quatro caminhos para proxy: o ProxyAgent do undici, o dispatcher global, a variável de ambiente `NODE_USE_ENV_PROXY` e o agente de proxy do Axios. Adicionar desde o início o tempo limite, o tratamento de erro, a nova tentativa com espera exponencial e o limite de concorrência torna os seus scripts muito mais confiáveis. Você encontra os pacotes adequados para tráfego web na nossa página de [Proxies HTTPS](https://proxynet.io/pt-br/https-proxy).
