🎯 Um navegador em nuvem personalizável e anti-detecção alimentado por Chromium desenvolvido internamente, projetado para rastreadores web e agentes de IA. 👉Experimente agora
De volta ao blog

ComoEnviar JSON com cURL: Guia Completo sobre -d, --json e Erros Comuns

Sophia Martinez
Sophia Martinez

Specialist in Anti-Bot Strategies

02-Jun-2026

Principais Conclusões:

  • Enviar JSON com cURL são duas coisas, não uma. Você anexa um corpo JSON à solicitação e informa ao servidor que é JSON através do cabeçalho Content-Type: application/json. Pule o cabeçalho e muitas APIs rejeitam ou interpretam mal o corpo.
  • -d/--data carrega o payload; o cabeçalho é por sua conta. O padrão clássico é curl -X POST -H "Content-Type: application/json" -d '{...}' URL. -d não define nenhum cabeçalho JSON por si só.
  • --json é o atalho moderno. Adicionado no curl 7.82.0, --json '{...}' envia o corpo e define tanto Content-Type: application/json quanto Accept: application/json em uma única flag.
  • A citação no shell é onde a maioria das pessoas se queima. Envolva o JSON entre aspas simples para que o shell não consuma as aspas duplas dentro dele; no cmd do Windows, as regras são diferentes e um arquivo de payload é mais seguro.
  • @file lê o corpo do disco — mas escolha a flag de dados correta. -d @body.json remove quebras de linha; --data-binary @body.json e --json @body.json enviam o arquivo byte por byte.
  • A mesma forma de solicitação impulsiona APIs reais. Uma chamada JSON-RPC para o endpoint MCP hospedado da Scrapeless é apenas um POST com um corpo JSON e um cabeçalho de autenticação — o exato padrão que este guia ensina.
  • Gratuito para começar. Novas contas da Scrapeless incluem acesso gratuito ao tempo de execução do Scraping Browser e proxy residencial — inscreva-se em Scrapeless.

Introdução: a solicitação com a qual toda integração de API começa

Quase toda API web moderna fala JSON. Você autentica com um corpo JSON, envia um trabalho com um corpo JSON, chama uma ferramenta em um servidor MCP com um corpo JSON. Antes que qualquer uma dessas operações aconteça dentro de um script ou um SDK, geralmente começa como um único comando curl em um terminal — a maneira mais rápida de confirmar que um endpoint se comporta da maneira que a documentação afirma.

O problema é que "enviar JSON com curl" esconde dois requisitos separados que são fáceis de confundir. Um é anexar o texto JSON como o corpo da solicitação. O outro é declarar, através do cabeçalho Content-Type, que o corpo é JSON para que o servidor o interprete corretamente, em vez de tratá-lo como dados de formulário. Faça o corpo correto, mas esqueça o cabeçalho e uma API rigorosa retorna um 400 ou lê silenciosamente nada. Citar o JSON de forma errada no seu shell e o curl envia uma string confusa que nunca foi JSON válido para começar.

Este guia define exatamente o que "enviar JSON com curl" significa, passa pelas duas famílias de flags que fazem isso (-d mais um cabeçalho, e o novo --json), mostra exemplos práticos que você pode executar contra um endpoint público de eco e cataloga os erros que produzem os erros confusos. Conclui mapeando a mesma forma de solicitação para uma chamada real a uma API JSON — o endpoint MCP hospedado da Scrapeless — para que o padrão seja transportado diretamente do terminal para a produção. Para um contexto relacionado, veja nosso guia sobre raspagem HTTP assíncrona com aiohttp e a explicação sobre o que é um proxy SSL.


O que "Enviar JSON Com cURL" Significa

cURL (a ferramenta de linha de comando em torno do libcurl) transfere dados sobre HTTP e muitos outros protocolos. "Enviar JSON com cURL" significa emitir uma solicitação HTTP — quase sempre um POST, PUT ou PATCH — cujo corpo da solicitação é um documento JSON e cujo cabeçalho Content-Type é definido como application/json.

Essas duas partes são independentes e ambas são importantes:

  • O corpo é o texto JSON bruto — por exemplo {"product":"laptop","max_price":1200}. O curl envia esses bytes verbatim como a entidade da solicitação.
  • O cabeçalho Content-Type informa ao servidor como interpretar esses bytes. Sem ele, o padrão do curl para -d é application/x-www-form-urlencoded, o formato utilizado para envios de formulários HTML. Uma API JSON que vê esse cabeçalho pode recusar a solicitação ou tentar (e falhar) interpretar o corpo como campos de formulário.

Uma solicitação JSON correta, portanto, sempre associa um corpo JSON com o tipo de conteúdo JSON. A única questão é quais flags do curl você usa para produzir essa associação — e essa é a diferença entre a abordagem clássica de -d mais cabeçalho e o atalho de uma única flag --json abordado abaixo.

Uma rápida nota de terminologia: -d é a forma curta de --data, e -H é a forma curta de --header. Elas são intercambiáveis; este guia usa as formas curtas em exemplos e nomeia as formas longas onde isso ajuda.


Método 1: -d / --data Com um Cabeçalho Content-Type

Esta é a abordagem portátil, que funciona em todos os lugares e a que você verá na maioria da documentação da API. Você fornece o corpo com -d e o cabeçalho com -H:

bash Copy
curl -X POST https://httpbin.org/post \
  -H "Content-Type: application/json" \
  -d '{"product":"laptop","max_price":1200}'

Três coisas estão acontecendo:

  • -X POST define o método HTTP. Estritamente, -d já implica POST, então -X POST é opcional aqui — mas declará-lo torna a intenção explícita e é necessário se você mudar a flag do corpo de uma forma que, de outra maneira, seria definida como GET.
  • -H "Content-Type: application/json" declara o formato do corpo.
  • -d '{...}' anexa o JSON. As aspas simples impedem que o shell interprete as aspas duplas dentro do JSON.

Executar isso contra httpbin.org/post — um endpoint público que ecoa tudo o que recebe — retorna:

json Copy
{
  "data": "{\"product\":\"laptop\",\"max_price\":1200}",
  "headers": {
    "Accept": "*/*",
    "Content-Type": "application/json",
    "Host": "httpbin.org",
    "User-Agent": "curl/8.18.0"
  },
  "json": {
    "max_price": 1200,
    "product": "laptop"
  },
  "origin": "203.0.113.10",
  "url": "https://httpbin.org/post"
}
// Os valores dos campos são amostras ilustrativas; a estrutura é o que httpbin retorna.

O sinal chave de sucesso é o objeto json: httpbin só o preenche quando o corpo é analisado como JSON válido e o Content-Type era application/json. O cabeçalho Accept é */* — o padrão do curl — porque -d não altera Accept. Note que, por si só, -d não define nenhum cabeçalho JSON: o Content-Type acima está lá apenas porque você adicionou a linha -H. Se você remover essa linha, o httpbin reportaria Content-Type: application/x-www-form-urlencoded e um campo json vazio.


Método 2: A Flag --json (curl 7.82.0+)

A flag --json chegou no curl 7.82.0 (lançado no início de 2022) para reunir o caso comum em uma única opção. Verifique sua versão com curl --version; se reportar 7.82.0 ou mais recente, --json está disponível.

bash Copy
curl -X POST https://httpbin.org/post \
  --json '{"product":"laptop","max_price":1200}'

Um único --json faz três trabalhos ao mesmo tempo. Ele envia o texto fornecido como o corpo da solicitação e define ambos esses cabeçalhos para você:

  • Content-Type: application/json
  • Accept: application/json

Esse segundo cabeçalho é a diferença prática em relação ao Método 1: --json também informa ao servidor que você quer JSON de volta, o que algumas APIs usam para escolher seu formato de resposta. Ecoar a solicitação por meio do httpbin confirma isso:

json Copy
{
  "data": "{\"product\":\"laptop\",\"max_price\":1200}",
  "headers": {
    "Accept": "application/json",
    "Content-Type": "application/json",
    "Host": "httpbin.org",
    "User-Agent": "curl/8.18.0"
  },
  "json": {
    "max_price": 1200,
    "product": "laptop"
  },
  "origin": "203.0.113.10",
  "url": "https://httpbin.org/post"
}
// Note que tanto Accept quanto Content-Type agora são application/json.

Você pode passar --json mais de uma vez e o curl concatena os fragmentos em um único corpo — útil para montar uma carga útil a partir de partes. Se você precisar substituir um dos cabeçalhos que --json define (digamos, um Accept diferente), adicione um -H explícito depois disso; o cabeçalho mais recente prevalece.

Quando você deve usar cada método? Use --json para novos trabalhos em um curl atual. Use -d mais -H quando você precisar suportar versões mais antigas do curl, quando quiser controle total sobre quais cabeçalhos estão presentes ou quando a documentação que você está seguindo estiver escrita dessa maneira.

Comportamento -d '{...}' -d '{...}' -H "Content-Type: application/json" --json '{...}'
Envia o JSON como corpo Sim Sim Sim
Método HTTP padrão POST POST POST
Define Content-Type: application/json Não (padrão para form-urlencoded) Sim (você define) Sim (automático)
Define Accept: application/json Não Não Sim (automático)
Versão mínima do curl Qualquer Qualquer 7.82.0

Obtenha sua chave de API no plano gratuito: Scrapeless


Enviando um Arquivo JSON Com @

JSON em linha se torna inviável após alguns campos, e cargas úteis grandes pertencem a um arquivo. Tanto -d quanto --json aceitam o prefixo @ para ler o corpo a partir de um caminho. Dado um body.json como:

json Copy
{
  "product": "laptop",
  "max_price": 1200
}

Você pode enviá-lo com qualquer uma das flags:

bash Copy
# Clássico: flag de dados + cabeçalho explícito
curl -X POST https://httpbin.org/post \
  -H "Content-Type: application/json" \
  -d @body.json

# Moderno: uma flag
curl -X POST https://httpbin.org/post \
  --json @body.json

Há uma diferença sutil, mas importante, em como o arquivo é lido. -d @body.json remove quebras de linha e retornos de carro do arquivo antes de enviar — uma herança de -d ser projetado para dados de formulário. O corpo que chega ao servidor torna-se { "product": "laptop", "max_price": 1200}: ainda JSON válido (espaçamento entre tokens é permitido), mas não é mais byte por byte o que está no disco.

Duas flags preservam o arquivo exatamente:

bash Copy
# --data-binary mantém cada byte, incluindo quebras de linha
curl -X POST https://httpbin.org/post \
  -H "Content-Type: application/json" \
  --data-binary @body.json

# --json @file também envia o arquivo literalmente

curl -X POST https://httpbin.org/post
--json @body.json

Copy
Para JSON comum, a versão sem quebras de linha ainda é analisável, então `-d @file` geralmente funciona. Mas se o payload deve corresponder ao arquivo byte por byte — uma assinatura é computada sobre os bytes exatos ou o arquivo contém um valor de string com quebras de linha significativas incorporadas — use `--data-binary @file` ou `--json @file`.

Você também pode enviar um corpo a partir da entrada padrão usando `@-`, o que é conveniente quando outro programa gera o JSON:

```bash
generate_payload | curl -X POST https://httpbin.org/post --json @-

Erros Comuns (e Como Evitá-los)

Estas são as falhas que transformam um curl de cinco segundos em uma sessão de depuração.

1. Esquecer o cabeçalho Content-Type

A mais comum. Com -d simples e sem cabeçalho, curl envia Content-Type: application/x-www-form-urlencoded. Uma API JSON pode rejeitar a solicitação com um 4xx ou ler um corpo vazio. Solução: adicione -H "Content-Type: application/json", ou mude para --json, que configura isso para você.

2. Citação de shell que quebra o JSON

JSON usa aspas duplas; a maioria das shells também usa aspas duplas para interpolação. Envolver um payload em aspas duplas permite que a shell remova ou expanda partes dele antes que o curl o veja:

bash Copy
# ERRADO no bash/zsh: a shell consome as aspas duplas internas
curl -X POST https://httpbin.org/post --json "{"product":"laptop"}"

# CERTO: use aspas simples para todo o payload
curl -X POST https://httpbin.org/post --json '{"product":"laptop"}'

Solução: envolva todo o documento JSON em aspas simples no bash/zsh. Se um valor em si precisar conter uma aspa simples literal, escape-a ou mova o payload para um arquivo e use @file — o que contorna totalmente a citação da shell.

3. Citação do cmd do Windows é diferente

O cmd.exe do Windows não trata aspas simples como caracteres de citação, então o truque das aspas simples falha lá. Você deve escapar cada aspa dupla interna com uma barra invertida, ou — muito mais confiável — colocar o JSON em um arquivo e enviar @body.json. O PowerShell tem suas próprias regras de citação e seu alias curl historicamente aponta para Invoke-WebRequest; chame curl.exe explicitamente e prefira a forma @file para evitar surpresas. Solução: no Windows, use um arquivo de payload com @body.json.

4. Deixar -G transformar seu corpo em uma string de consulta

-G/--get diz ao curl para anexar dados -d à URL como parâmetros de consulta em vez de enviar um corpo. Esta é a ferramenta certa para solicitações GET, mas se você deixá-la ativa enquanto tenta POSTAR JSON, seu payload silenciosamente se move para a URL e o corpo fica vazio. Solução: não combine -G com um corpo JSON; use -X POST (ou deixe -d/--json padrão para POST).

5. Enviar JSON inválido

curl não valida o corpo — ele envia qualquer texto que você fornecer. Uma vírgula final, uma chave não colocada entre aspas ou uma string com aspas simples é algo que o servidor irá rejeitar, muitas vezes com um erro de análise opaco. Solução: valide o payload antes de enviar. Uma rápida verificação local com um parser JSON captura a maioria:

bash Copy
# Falha rapidamente em JSON malformado antes de o curl ser executado
echo '{"product":"laptop","max_price":1200}' | python -c "import sys, json; json.load(sys.stdin); print('valid')"

6. Esquecer Accept quando a API negocia conteúdo

Algumas APIs retornam XML ou HTML, a menos que você peça JSON. Com -d você apenas define Content-Type, não Accept, então a resposta pode não ser JSON, mesmo que sua solicitação tenha sido. Solução: adicione -H "Accept: application/json", ou use --json, que define Accept para você.


Exemplo Prático: Chamando uma API JSON

Juntando tudo, aqui está a forma de uma chamada real à API JSON. O endpoint hospedado Scrapeless MCP fala JSON-RPC sobre HTTP — ou seja, é exatamente a solicitação que você tem construído: um POST com um corpo JSON e um cabeçalho de autenticação. Leia a chave da API de uma variável de ambiente para que ela nunca apareça no seu histórico de shell:

bash Copy
# O corpo vive em init.json; a chave vem do ambiente, não da linha de comando
curl -X POST "https://api.scrapeless.com/mcp" \
  -H "x-api-token: ${SCRAPELESS_API_KEY}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  --data-binary @init.json

com init.json contendo o handshake JSON-RPC:

json Copy
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {
    "protocolVersion": "2024-11-05",
    "capabilities": {},
    "clientInfo": { "name": "curl-demo", "version": "1.0" }
  }
}

Cada conceito deste guia está presente: um corpo JSON (aqui de um arquivo, enviado verbalmente com --data-binary), o cabeçalho Content-Type: application/json que o marca como JSON, um cabeçalho Accept que nomeia os formatos que você aceitará de volta e um cabeçalho de autenticação contendo a credencial. O endpoint hospedado expõe cerca de duas dúzias de ferramentas — google_search, scrape_html, scrape_markdown, o conjunto de automação browser_* e mais — cada uma invocada com o mesmo padrão POST-a-JSON-body, apenas mudando o method e params. Detalhes de configuração estão nos documentos do Scrapeless.

Você não precisa continuar se comunicando com o endpoint em curl puro, claro — mas provar um endpoint com curl primeiro e depois portar a solicitação verificada para sua linguagem de escolha é o fluxo de trabalho que economiza mais tempo. Para o catálogo completo de ferramentas do servidor MCP e prompts de agentes trabalhados, veja 5 casos de uso do Scrapeless MCP.


Como o Scrapeless se Encaixa

Uma vez que um comando curl funcione, o próximo passo geralmente é fazê-lo em escala — muitas solicitações, contra sites que renderizam conteúdo com JavaScript ou que detectam tráfego automatizado. É aí que a forma da solicitação que você acabou de aprender encontra uma infraestrutura gerenciada.

Scrapeless fornece um navegador em nuvem anti-detecção — o Navegador de Scraping Scrapeless — e proxies residenciais em mais de 195 países, acessíveis através do endpoint MCP hospedado, um SDK e uma CLI. O navegador renderiza páginas pesadas em JavaScript no lado da nuvem e gerencia impressões digitais, de modo que a solicitação JSON limpa que você prototipou em curl retorna dados estruturados em vez de uma página de desafio. O detalhe do transporte — fixar uma saída residencial, persistir uma sessão — é tratado para você; seu lado permanece o mesmo simples loop "POST um corpo JSON, leia JSON de volta".

Explore o produto Navegador de Scraping, revise os planos na página de preços e encontre a referência da API e MCP na documentação.


Conclusão

Enviar JSON com curl resume-se a dois requisitos feitos juntos: anexar o JSON como corpo da solicitação e declará-lo como JSON com o cabeçalho Content-Type. A maneira clássica é -d '{...}' mais -H "Content-Type: application/json"; a moderna maneira de uma flag é --json '{...}', que define tanto Content-Type quanto Accept para você no curl 7.82.0 ou mais recente. Mova cargas grandes ou assinadas para um arquivo e envie-as com --data-binary @file ou --json @file para preservar cada byte, use aspas simples em JSON inline no bash para sobreviver à citação do shell, e busque por um arquivo de carga no Windows. A mesma solicitação — corpo mais tipo de conteúdo mais um cabeçalho de autenticação — é exatamente como chamar uma API JSON real como o endpoint MCP Scrapeless, que é por isso que um curl que funciona em seu terminal se porta de forma limpa para produção. Para leitura relacionada, veja raspagem HTTP assíncrona com aiohttp e o que é um proxy SSL.


FAQ

Q: Qual é a maneira mais simples de enviar JSON com curl?

Em um curl atual (7.82.0 ou mais recente), curl --json '{"key":"value"}' URL é a forma correta mais curta — ele envia o corpo e define tanto os cabeçalhos Content-Type quanto Accept para application/json. Em curl mais antigo, use curl -X POST -H "Content-Type: application/json" -d '{"key":"value"}' URL.

Q: Por que minha API JSON diz que o corpo está ausente ou inválido, mesmo que eu o tenha enviado?

Duas causas habituais. Ou você enviou -d sem um cabeçalho Content-Type: application/json, então o servidor leu como dados de formulário — adicione o cabeçalho ou use --json. Ou seu shell danificou o JSON porque estava envolvido em aspas duplas; coloque aspas simples na carga ou mova para um arquivo e envie @file.

Q: Qual é a diferença entre -d, --data-binary e --json?

-d (--data) envia o corpo e, para @file, remove novas linhas; não define nenhum cabeçalho JSON por conta própria. --data-binary envia o corpo exatamente como dado, com novas linhas e tudo. --json envia o corpo verbatim e define Content-Type e Accept como application/json; requer curl 7.82.0 ou mais recente.

Q: Como eu envio um arquivo JSON em vez de texto inline?

Prefixe o caminho com @: curl --json @body.json URL, ou curl -H "Content-Type: application/json" --data-binary @body.json URL. Prefira --json @file ou --data-binary @file em vez de -d @file quando os bytes precisam coincidir exatamente com o arquivo, pois -d @file remove novas linhas.

Q: Como envio JSON com curl no Windows?

cmd.exe não honra aspas simples, então o caminho mais fácil e confiável é colocar o JSON em um arquivo e enviá-lo com @body.json. Se você precisar inline, escape cada aspas dupla interna com uma barra invertida. No PowerShell, chame curl.exe explicitamente para não atingir o alias Invoke-WebRequest e ainda prefira a forma @file.
P: Preciso definir o cabeçalho Content-Type se eu usar --json?

Não. --json define automaticamente Content-Type: application/json, juntamente com Accept: application/json. Você só adicionaria um cabeçalho explícito para substituir um desses — por exemplo, um Accept diferente — nesse caso, coloque o -H após --json para que tenha prioridade.


Pronto para Construir Seu Pipeline de Dados Impulsionado por IA?

Junte-se à nossa comunidade para reivindicar um plano gratuito e conectar-se com desenvolvedores que estão construindo pipelines de coleta de dados baseados em JSON: Discord · Telegram.

Inscreva-se em Scrapeless para acesso gratuito ao ambiente de execução do Scraping Browser e proxy residencial, e transforme a solicitação curl que você prototipou em um pipeline de dados de produção.


Na Scorretless, acessamos apenas dados disponíveis ao público, enquanto cumprem estritamente as leis, regulamentos e políticas de privacidade do site aplicáveis. O conteúdo deste blog é apenas para fins de demonstração e não envolve atividades ilegais ou infratoras. Não temos garantias e negamos toda a responsabilidade pelo uso de informações deste blog ou links de terceiros. Antes de se envolver em qualquer atividade de raspagem, consulte seu consultor jurídico e revise os termos de serviço do site de destino ou obtenha as permissões necessárias.

Artigos mais populares

Catálogo