Network Requests

Fetch API & AJAX

Todo app web moderno se comunica com um servidor. A Fetch API é a maneira padrão de enviar requisições, ler respostas e atualizar a página sem a necessidade de um recarregamento completo.

intermediate15 min readUpdated 15 de set. de 2026
js
// api.js
async function getUsers() {
  const res = await fetch("/api/users", {
    headers: { Accept: "application/json" },
  });
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  return res.json();
}

const users = await getUsers();
console.log(users);
Padrão
Parte do Fetch Living Standard
Retorna
Uma Promise<Response>
Substitui
XMLHttpRequest
Lê o corpo como
json, text, blob, formData
Cancela com
AbortController
Rejeita em
Apenas erros de rede

Pratico

Tente uma requisição fetch

Esta demo busca uma URL de dados JSON, portanto, funciona offline.

Tente uma requisição fetch

Esta demo busca uma URL de dados JSON, portanto, funciona offline.

Por que importa

Por que o fetch é importante

Uma API para tudo

A mesma chamada fetch lida com APIs JSON, texto, arquivos, streams e dados de formulário em diferentes navegadores e runtimes.

Baseado em Promises

O fetch retorna uma promise, portanto, compõe-se perfeitamente com async/await e combinadores de Promise.

Seguro por padrão

Configurações padrão sensatas sobre CORS e credenciais ajudam você a evitar vazamentos acidentais de dados.

O panorama completo

As três partes de cada requisição

Uma requisição de rede consiste em uma solicitação, uma resposta e o tratamento de erros ao redor delas. Acerte esses três pontos e o restante são detalhes.

A requisição

Enviar

A URL, o método, os headers e o corpo descrevem exatamente o que você deseja que o servidor faça.

A resposta

Ler

Status, headers e um corpo que você analisa como JSON, texto, um blob ou um stream.

Os erros

Recuperar

Diferencie falhas de rede de status de erro HTTP e, então, mostre algo útil ao usuário.

Fetch em resumo

O que a Fetch API oferece

Requisições GET

Busca dados de uma URL e lê o corpo da resposta.

POST & PUT

Envia dados para o servidor com um método, headers e um corpo.

Lendo JSON

res.json() analisa o corpo da resposta em um valor JavaScript.

Tratamento de erros

Verifique res.ok para erros HTTP e use catch para falhas de rede.

Cancelamento

AbortController interrompe requisições que não são mais necessárias.

CORS & credenciais

Entenda origens, requisições preflight e quando os cookies são enviados.

Uma breve historia

De XMLHttpRequest ao fetch

  1. 1999

    XMLHttpRequest

    A Microsoft introduz o XHR, e a era AJAX começa.

    99
  2. 2005

    AJAX torna-se mainstream

    Gmail e Google Maps provam que páginas podem ser atualizadas sem recarregar.

    05
  3. 2015

    A Fetch API

    Um substituto mais limpo e baseado em promises para o XHR chega aos navegadores.

    15
  4. 2017

    async / await

    O fetch torna-se drasticamente mais legível com a nova sintaxe.

    17
  5. Hoje

    O padrão

    Fetch é a API de requisição padrão em navegadores, Node.js, Deno e runtimes de edge.

    Hoje

O guia completo

Fetch API & AJAX: Tudo que voce precisa saber

O que é AJAX?

AJAX significa Asynchronous JavaScript and XML, um termo cunhado em 2005 quando o Gmail e o Google Maps mostraram pela primeira vez que uma página poderia buscar novos dados sem a necessidade de um recarregamento completo. A parte do XML é majoritariamente história — APIs modernas retornam JSON — mas a ideia central permanece: comunicar-se com um servidor em segundo plano e atualizar a página dinamicamente.

A ferramenta original era o XMLHttpRequest. Ele funciona, mas sua API é desajeitada e baseada em callbacks. A substituição moderna é a Fetch API, uma interface baseada em promises disponível em navegadores, Node.js, Deno e runtimes de edge.

Sua primeira requisição fetch

fetch recebe uma URL e retorna uma promise para um Response.

// basic.js
const response = await fetch("https://api.example.com/users");
const users = await response.json();

console.log(users);

Esse é todo o “caminho feliz”. O detalhe é que fetch é resolvida mesmo para códigos de status de erro, portanto, um 404 não lança uma exceção. Você mesmo deve inspecionar a resposta.

O objeto Response

O objeto Response informa o que o servidor enviou de volta.

// response.js
const response = await fetch("/api/users");

response.ok;      // true for status 200–299
response.status;  // 200, 404, 500, ...
response.statusText;
response.headers.get("content-type");

const data = await response.json();   // parse JSON
const text = await response.text();   // raw text
const blob = await response.blob();   // binary data
const form = await response.formData();

O corpo (body) só pode ser lido uma vez. Se você precisar tanto do texto bruto quanto do JSON analisado, chame response.clone() antes de ler, ou analise o texto manualmente. Note também que response.json() retorna uma rejeição se o corpo não for um JSON válido — outro motivo para envolver as chamadas em try/catch.

Tratando erros adequadamente

Existem dois tipos de falhas, e elas se comportam de maneira diferente.

  1. Erros de rede — sem conexão, falha de DNS, CORS bloqueado. fetch é rejeitado, então catch os trata.
  2. Erros de HTTP — 404, 401, 500. fetch é resolvido; você deve verificar response.ok ou response.status.
// errors.js
async function getUser(id) {
  try {
    const response = await fetch(`/api/users/${id}`);
    if (!response.ok) {
      throw new Error(`Request failed with status ${response.status}`);
    }
    return await response.json();
  } catch (error) {
    console.error("Could not load user:", error);
    throw error;
  }
}

Tratar ambos os casos explicitamente é o que separa um código frágil de um código resiliente. O guia de Tratamento de Erros aborda a estratégia de forma mais ampla.

Enviando dados com POST, PUT e DELETE

Passe um objeto de opções para alterar o método, adicionar headers e anexar um corpo (body).

// create.js
async function createUser(user) {
  const response = await fetch("/api/users", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Accept: "application/json",
    },
    body: JSON.stringify(user),
  });

  if (!response.ok) throw new Error("Could not create user");
  return response.json();
}

await createUser({ name: "Ada", role: "engineer" });

Use PUT para substituir um recurso, PATCH para atualizar parte dele e DELETE para removê-lo. Para uploads de arquivos, crie um objeto FormData e passe-o como o body — o navegador definirá o content type multipart correto para você.

Headers e autenticação

Os headers carregam metadados sobre a requisição. Você pode defini-los por requisição, e muitas APIs esperam um token de autorização.

// auth.js
const response = await fetch("/api/me", {
  headers: {
    Authorization: `Bearer ${token}`,
    Accept: "application/json",
  },
});

Nunca escreva segredos diretamente (hard-code) no código do lado do cliente — qualquer coisa enviada ao navegador é pública. Os tokens devem vir de um fluxo de login e ser armazenados com cuidado.

Cancelando requisições

Uma requisição que não é mais relevante — o usuário digitou outro caractere, navegou para outra página ou o componente foi desmontado — deve ser cancelada. AbortController faz exatamente isso.

// abort.js
const controller = new AbortController();

fetch("/api/search?q=javascript", { signal: controller.signal })
  .then((res) => res.json())
  .then(console.log)
  .catch((error) => {
    if (error.name === "AbortError") return;
    console.error(error);
  });

// Cancel when it is no longer needed
controller.abort();

Como o fetch não possui uma opção de timeout, o AbortController também é a maneira padrão de implementar um.

// timeout.js
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), 5000);

try {
  const res = await fetch("/api/slow", { signal: controller.signal });
  return await res.json();
} finally {
  clearTimeout(timer);
}

CORS e credenciais

Os navegadores aplicam a same-origin policy: o JavaScript não pode ler respostas de uma origem diferente, a menos que o servidor permita. Essa permissão é o CORS, e ele é configurado inteiramente no servidor por meio de headers de resposta como Access-Control-Allow-Origin. Se você encontrar um erro de CORS, a correção deve ser feita na configuração do servidor, e não na sua chamada de fetch.

Por padrão, fetch não envia cookies para URLs de origens diferentes. Para incluí-los, defina credentials: "include" e certifique-se de que o servidor permite requisições com credenciais. Esta é uma causa comum da confusão do tipo “funciona no Postman, mas não no navegador”.

Padrões práticos

Estados de carregamento, sucesso e erro. Sempre reflita o ciclo de vida da requisição na UI.

// state.js
async function loadPosts() {
  showSpinner();
  try {
    const res = await fetch("/api/posts");
    if (!res.ok) throw new Error(`HTTP ${res.status}`);
    renderPosts(await res.json());
  } catch (error) {
    showError("Could not load posts. Try again.");
  } finally {
    hideSpinner();
  }
}

Busca com debounce. Cancele a requisição anterior sempre que uma nova for iniciada, para que respostas lentas não sobrescrevam resultados recentes. Combine AbortController com um pequeno atraso de debounce.

Requisições paralelas. Use Promise.all quando vários endpoints forem necessários simultaneamente, e Promise.allSettled quando um resultado parcial ainda for útil.

Melhores práticas

  • Sempre verifique response.ok antes de fazer o parsing do corpo.
  • Defina um header Accept explícito e um Content-Type ao enviar um corpo.
  • Envolva requisições com await em try/catch e exiba uma mensagem útil.
  • Cancele requisições obsoletas com AbortController.
  • Mantenha as chamadas de API em um módulo pequeno em vez de espalhar URLs pelos componentes.
  • Nunca coloque segredos (secrets) no código do lado do cliente.
  • Exiba estados de carregamento e de erro para que a UI nunca pareça quebrada.

Erros comuns

  • Assumir que fetch lança um erro em casos de 404 ou 500.
  • Esquecer o JSON.stringify no corpo de uma requisição.
  • Esquecer o header Content-Type e receber um erro de parse do servidor.
  • Ler o corpo de uma resposta duas vezes.
  • Ignorar o CORS até que o navegador bloqueie a requisição em produção.
  • Deixar requisições sem cancelamento, permitindo que dados obsoletos vençam uma race condition.

Próximos passos

O Fetch é a ponte entre o seu front end e o mundo. Combine-o com o DOM para renderizar resultados, async/await para sequenciar tarefas e tratamento de erros para lidar com falhas de forma elegante. A partir daí, aprofunde seus conhecimentos sobre métodos, códigos de status e headers, já que eles moldam cada requisição que você envia.

Verificando a resposta

O fetch só rejeita em falhas de rede. Um 404 ou 500 ainda resolve, então verifique res.ok.

Preferível
const res = await fetch("/api/data");
if (!res.ok) {
  throw new Error(`HTTP ${res.status}`);
}
const data = await res.json();
Evite
const res = await fetch("/api/data");
const data = await res.json();
// silently parses error pages

Enviando JSON

Informe ao servidor o que você está enviando e transforme o corpo em string.

Preferível
await fetch("/api/users", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ name: "Ada" }),
});
Evite
await fetch("/api/users", {
  method: "POST",
  body: { name: "Ada" },
});

Perguntas frequentes

Perguntas frequentes

Keep learning

Related topics from the roadmap.

$ comecar a aprender

Pronto para aprender Fetch API & AJAX?

Nosso tutorial interativo te guia por Fetch API & AJAX passo a passo — com quizzes e codigo real que voce pode executar no navegador.