> Le guide complet de fetch en JavaScript : GET, POST, headers, body, réponses JSON, async/await, gestion des erreurs, AbortController et CORS expliqués simplement.

*Source : https://coder-studio.com/tutoriels/fetch-api-javascript/*

---

[// Web](https://coder-studio.com/tutoriels/)

# L'API Fetch en JavaScript : requêtes HTTP modernes

Par **Kévin Papot** · publié le 18 novembre 2025

L’**API Fetch** est la manière moderne d’envoyer des requêtes HTTP en JavaScript, directement dans le navigateur, sans bibliothèque externe. Récupérer des données d’une API, envoyer un formulaire, télécharger un fichier : tout passe par la fonction globale `fetch()`. Elle repose sur les Promesses, s’écrit très bien avec `async/await` et remplace définitivement l’ancien `XMLHttpRequest`. Ce guide couvre chaque aspect, du simple GET à l’annulation d’une requête, avec un exemple concret à chaque étape.

## La requête la plus simple : un GET

Dans sa forme minimale, `fetch()` prend une URL et renvoie une Promesse qui se résout avec un objet `Response`. Ce n’est pas encore les données : c’est une enveloppe qu’il faut « ouvrir » avec une méthode comme `.json()`.

```
fetch("https://jsonplaceholder.typicode.com/todos/1")
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error("Erreur :", error));
```

Le premier `.then` reçoit la réponse et la convertit en JSON (ce qui renvoie une nouvelle Promesse), le second reçoit enfin les données exploitables. Cette double étape déroute souvent les débutants : retenez que `fetch` résout d’abord les _en-têtes_ de la réponse, puis `.json()` lit le _corps_.

## La version async/await, plus lisible

Enchaîner les `.then` devient vite illisible. La syntaxe `async/await` transforme ce code asynchrone en quelque chose qui se lit de haut en bas, comme du code synchrone.

```
async function chargerTodo() {
  const response = await fetch("https://jsonplaceholder.typicode.com/todos/1");
  const data = await response.json();
  console.log(data);
}

chargerTodo();
```

C’est la forme que vous utiliserez le plus souvent. Elle suppose de maîtriser le fonctionnement des [Promesses et de async/await](https://coder-studio.com/tutoriels/async-await-promesses-js/), sur lequel repose entièrement Fetch. Notez qu’`await` ne peut s’utiliser qu’à l’intérieur d’une fonction `async`.

## Lire la réponse : json, text, blob

L’objet `Response` sait interpréter le corps sous plusieurs formats. Vous choisissez la méthode selon ce que renvoie le serveur.

```
const response = await fetch("/donnees");

// API JSON (le cas le plus fréquent)
const objet = await response.json();

// Texte brut, HTML, CSV…
const texte = await response.text();

// Données binaires : images, fichiers, PDF
const image = await response.blob();

// Données binaires bas niveau
const buffer = await response.arrayBuffer();
```

Attention : le corps d’une réponse ne peut être lu **qu’une seule fois**. Appeler `response.json()` puis `response.text()` sur la même réponse déclenche une erreur. Choisissez la bonne méthode d’emblée.

## Envoyer des données : la requête POST

Pour créer une ressource, on passe un second argument à `fetch` : un objet d’options. Les trois clés essentielles sont `method`, `headers` et `body`.

```
async function creerArticle() {
  const response = await fetch("https://jsonplaceholder.typicode.com/posts", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      titre: "Mon article",
      contenu: "Écrit avec Coder Studio",
      userId: 1,
    }),
  });

  const cree = await response.json();
  console.log("Ressource créée :", cree);
}
```

Trois points cruciaux :

-   `method` vaut `"POST"`, `"PUT"`, `"PATCH"` ou `"DELETE"` selon l’action ;
-   `body` doit être une **chaîne** : on sérialise l’objet JavaScript avec `JSON.stringify` ;
-   l’en-tête `Content-Type: application/json` prévient le serveur du format envoyé. L’oublier est une cause d’erreur très courante.

### Les autres méthodes HTTP

La structure reste identique, seule la valeur de `method` change. Un `DELETE` n’a généralement pas de corps :

```
// Mise à jour complète
await fetch(`/articles/${id}`, {
  method: "PUT",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify(articleModifie),
});

// Suppression
await fetch(`/articles/${id}`, { method: "DELETE" });
```

Ces verbes forment la base d’une [API REST](https://coder-studio.com/tutoriels/api-rest-guide/), la convention d’échange standard entre le front-end et le back-end.

## Les en-têtes (headers)

Les en-têtes transmettent des métadonnées : format attendu, jeton d’authentification, langue… On les passe dans un objet simple.

```
const response = await fetch("/api/profil", {
  headers: {
    "Content-Type": "application/json",
    "Authorization": "Bearer " + token,
    "Accept": "application/json",
    "Accept-Language": "fr-FR",
  },
});
```

L’en-tête `Authorization` avec un jeton `Bearer` est le mécanisme d’authentification le plus répandu pour les API. Vous lirez souvent aussi les en-têtes de la _réponse_ :

```
console.log(response.headers.get("Content-Type"));
```

## La gestion des erreurs : le piège classique

Voici le point le plus mal compris de Fetch. Une réponse 404 ou 500 **ne déclenche pas** le `.catch` ni le bloc `catch` d’un `try/catch`. La Promesse n’est rejetée que sur une erreur _réseau_ (pas de connexion, DNS injoignable, requête bloquée). Une réponse serveur, même en erreur, est considérée comme un succès de communication.

Il faut donc vérifier soi-même le statut avec la propriété `response.ok` (vraie pour un statut 200–299).

```
async function chargerDonnees(url) {
  try {
    const response = await fetch(url);

    if (!response.ok) {
      // 404, 500… : à gérer explicitement
      throw new Error(`Erreur HTTP ${response.status} : ${response.statusText}`);
    }

    const data = await response.json();
    return data;
  } catch (error) {
    // Ici : erreur réseau OU erreur HTTP relancée ci-dessus
    console.error("Échec du chargement :", error.message);
    return null;
  }
}
```

Ce schéma — tester `response.ok`, lever une erreur, tout envelopper dans `try/catch` — est le motif à reproduire dans chaque appel. La propriété `response.status` contient le code numérique (200, 404, 500…) et `response.statusText` son libellé.

## Annuler une requête avec AbortController

Une requête peut devenir inutile avant sa fin : l’utilisateur quitte la page, tape une nouvelle recherche, ou l’attente est trop longue. `AbortController` permet de l’interrompre proprement.

```
const controller = new AbortController();

// On passe le signal à fetch
fetch("/api/recherche?q=javascript", { signal: controller.signal })
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => {
    if (error.name === "AbortError") {
      console.log("Requête annulée");
    } else {
      console.error(error);
    }
  });

// Plus tard : on annule
controller.abort();
```

Cas très pratique : un **timeout** maison qui annule automatiquement après quelques secondes.

```
async function fetchAvecTimeout(url, ms = 5000) {
  const controller = new AbortController();
  const id = setTimeout(() => controller.abort(), ms);

  try {
    const response = await fetch(url, { signal: controller.signal });
    return await response.json();
  } finally {
    clearTimeout(id);
  }
}
```

Sur les navigateurs récents, `AbortSignal.timeout(5000)` fait la même chose en une ligne, mais la version manuelle reste utile à comprendre.

## Les requêtes en parallèle

Quand plusieurs requêtes sont indépendantes, ne les enchaînez pas : lancez-les ensemble avec `Promise.all` pour gagner un temps précieux.

```
async function chargerTableauDeBord() {
  const [profil, articles, notifs] = await Promise.all([
    fetch("/api/profil").then(r => r.json()),
    fetch("/api/articles").then(r => r.json()),
    fetch("/api/notifications").then(r => r.json()),
  ]);

  console.log(profil, articles, notifs);
}
```

Les trois requêtes partent simultanément ; on attend seulement la plus lente au lieu de les additionner.

## CORS en bref

Le **CORS** (Cross-Origin Resource Sharing) est la source d’erreur la plus frustrante pour les débutants. Par sécurité, le navigateur bloque par défaut les requêtes JavaScript vers un domaine _différent_ de celui de votre page, sauf si le serveur cible l’autorise explicitement via des en-têtes (`Access-Control-Allow-Origin`).

Point essentiel à comprendre : **le CORS se règle côté serveur, pas côté client**. Aucune option de `fetch` ne « débloque » le CORS. Si vous voyez une erreur _No ‘Access-Control-Allow-Origin’ header_, c’est au serveur d’être configuré, ou il faut passer par votre propre back-end comme intermédiaire (proxy). L’option `mode: "cors"` (par défaut) et l’option `credentials: "include"` (pour envoyer les cookies) ajustent le comportement, mais ne contournent pas la règle de sécurité.

## À retenir

`fetch()` renvoie une Promesse résolue avec un objet `Response` qu’il faut « ouvrir » avec `.json()`, `.text()` ou `.blob()`. Pour un POST, sérialisez le corps avec `JSON.stringify` et déclarez le bon `Content-Type`. Surtout, souvenez-vous que Fetch **ne rejette pas** sur les statuts 4xx et 5xx : testez toujours `response.ok`. Avec `async/await`, la gestion d’erreurs par `try/catch` et `AbortController` pour l’annulation, vous disposez de tout l’outillage HTTP moderne, sans aucune dépendance.

## À lire ensuite

-   [Promesses et async/await en JavaScript](https://coder-studio.com/tutoriels/async-await-promesses-js/)
-   [Comprendre les API REST](https://coder-studio.com/tutoriels/api-rest-guide/)
-   [Manipuler le DOM en JavaScript](https://coder-studio.com/tutoriels/manipuler-dom-javascript/)
