Les codes de statut HTTP sont organisés en cinq classes : 2xx pour les succès, 3xx pour les redirections, 4xx pour les erreurs client, et 5xx pour les erreurs serveur. Des codes comme 401, 403, 404, 422 et 500 apparaissent dans presque toutes les suites de tests API.

Comment les codes de statut sont organisés

Les codes de statut HTTP sont des nombres à trois chiffres organisés en cinq classes :

| Plage | Classe | Signification |

|-------|--------|--------------|

| 1xx | Informationnelle | Requête reçue, traitement en cours |

| 2xx | Succès | Requête traitée avec succès |

| 3xx | Redirection | Le client doit effectuer une autre action (généralement suivre une redirection) |

| 4xx | Erreur client | La requête pose problème : le client a envoyé quelque chose d'incorrect |

| 5xx | Erreur serveur | La requête était valide : le serveur n'a pas pu la traiter |

Le premier chiffre indique la catégorie. 4xx = votre requête était incorrecte. 5xx = le serveur a planté.

2xx : codes de succès

200 OK

Le code de succès le plus courant. La requête a fonctionné et il y a du contenu dans la réponse.

Utilisé pour : les requêtes GET qui retournent des données, les requêtes POST qui ne créent pas de ressource (comme une recherche), et les mises à jour PUT/PATCH. Quoi vérifier dans les tests : le body contient les données attendues, la réponse est dans le bon format (JSON, XML), et les champs requis sont présents.

201 Created

Une ressource a été créée avec succès. Doit être retourné pour les requêtes POST qui créent de nouveaux éléments.

Quoi vérifier : la réponse inclut la ressource créée avec son nouvel ID, le header Location pointe souvent vers l'URL de la nouvelle ressource, et POST /users doit retourner 201 avec { id: 123, email: "...", ... }. Bug courant à détecter : L'API retourne 200 au lieu de 201 pour les endpoints de création. Techniquement ça fonctionne, mais c'est sémantiquement incorrect et peut désorienter les consommateurs.

204 No Content

Succès, mais rien à retourner. Utilisé pour les requêtes DELETE et certaines réponses PUT/PATCH.

Quoi vérifier : le body de la réponse est vide (certaines API retournent incorrectement un body avec 204) et la ressource a bien été supprimée, vérifiable avec un GET ensuite.

206 Partial Content

Retourné quand une partie seulement d'une ressource est envoyée (téléchargements fragmentés, streaming vidéo). Principalement pertinent pour tester les téléchargements de fichiers et le streaming média.

3xx : codes de redirection

301 Moved Permanently

La ressource a définitivement déménagé vers une nouvelle URL. Les moteurs de recherche mettent à jour leurs indexes pour les 301.

Pertinence pour les tests : Vérifiez que les anciennes URLs redirigent correctement, que les redirections HTTPS depuis HTTP sont des 301 (pas des 302), et que les destinations des redirections se chargent correctement.

302 Found (redirection temporaire)

La ressource est temporairement sur une URL différente. Utilisé pour les redirections de connexion ("allez là maintenant, l'URL originale est toujours valide").

304 Not Modified

Le client a une version en cache qui est toujours d'actualité : aucun contenu envoyé, utilisez le cache. Vous verrez ça dans l'onglet Network du navigateur pour les ressources statiques.

Pertinence pour les tests : Si vous testez le comportement du cache, 304 signifie que le cache fonctionne. Si vous voyez 304 pour des données qui auraient dû changer, vous avez un bug de cache.

4xx : codes d'erreur client

Ces codes signifient que votre requête est le problème : mauvaises données, auth manquante, mauvaise URL.

400 Bad Request

Le serveur n'a pas pu comprendre la requête. Signifie généralement une syntaxe malformée, du JSON invalide, ou une erreur de validation.

Quand vous devriez voir un 400 : JSON invalide dans le body, header requis manquant, ou URL malformée. Quoi vérifier dans les tests : l'API retourne un message d'erreur utile, ne révèle pas de détails internes (stack traces), et retourne 400 plutôt que 500 pour une entrée invalide (un 500 ici est un bug serveur).

401 Unauthorized

La requête manque d'identifiants d'authentification valides. "Vous n'êtes pas connecté" ou "votre token a expiré".

Différence avec le 403 : 401 = non authentifié (qui êtes-vous ?). 403 = authentifié mais non autorisé (je sais qui vous êtes, mais vous ne pouvez pas faire ça). Quoi tester :
  • Requête sans token → 401
  • Requête avec un token expiré → 401
  • Requête avec un token invalide/falsifié → 401
  • La réponse d'erreur ne révèle pas d'informations sur les tokens valides

403 Forbidden

Authentifié, mais non autorisé. "Vous êtes connecté, mais vous n'avez pas la permission pour ça."

Quoi tester : un utilisateur régulier accédant à un endpoint admin doit obtenir 403, l'accès aux données privées d'un autre utilisateur aussi, et la réponse d'erreur ne doit pas exposer des données protégées. Pertinence sécurité : Un contrôle 403 manquant signifie que l'accès non autorisé fonctionne. C'est un vrai bug de sécurité.

404 Not Found

La ressource demandée n'existe pas à cette URL.

Quoi tester :
  • Demander une ressource supprimée → 404
  • Demander avec un ID jamais créé → 404
  • Ne pas révéler si la ressource existe pour les ressources sensibles (comptes utilisateur : retourner 404 "utilisateur introuvable" vs 403 "interdit" peut révéler l'existence d'un compte)
  • Est-ce un 404 ou un 410 ? (410 = supprimé définitivement, certaines API font la distinction)

405 Method Not Allowed

Vous avez utilisé la mauvaise méthode HTTP. GET sur un endpoint qui n'accepte que POST.

Pertinence pour les tests : Essayez délibérément de mauvaises méthodes, comme DELETE /users quand seul GET est prévu. Doit retourner 405, pas 500 ou un échec silencieux.

409 Conflict

La requête entre en conflit avec l'état actuel de la ressource.

Usages courants : créer un utilisateur avec un e-mail déjà existant, modifier une ressource verrouillée par quelqu'un d'autre, ou un conflit de version (optimistic locking). Quoi tester : la création en doublon doit retourner 409 (pas 200 ou 500) et la réponse doit expliquer clairement le conflit.

422 Unprocessable Entity

La requête était du JSON syntaxiquement valide, mais sémantiquement incorrect : la validation a échoué.

Exemple : Body JSON valide, mais age: -5 viole la règle que l'âge doit être positif. 400 vs 422 :
  • 400 = impossible de parser la requête (JSON incorrect, Content-Type erroné)
  • 422 = parsé correctement, mais les valeurs échouent à la validation

Beaucoup d'API utilisent 400 pour les deux cas. Ce qui compte, c'est la cohérence : choisissez l'un et utilisez-le correctement dans toute l'API.

Quoi tester : chaque champ requis manquant doit retourner 422 avec le nom du champ spécifique dans l'erreur, ainsi que les valeurs hors plage et les violations des règles métier.

429 Too Many Requests

Rate limiting : vous avez envoyé trop de requêtes en trop peu de temps.

Quoi tester : confirmer que les headers de rate limit sont retournés (X-RateLimit-Limit, X-RateLimit-Remaining, Retry-After). Vérifier aussi que les requêtes sont rejetées après la limite, puis qu'elles reprennent après expiration de la fenêtre. Pertinence sécurité : Les endpoints de connexion doivent limiter les requêtes pour prévenir les attaques par force brute. Testez que 429 est retourné après X tentatives de connexion échouées.

5xx : codes d'erreur serveur

Ce sont toujours des bugs. La requête était valide mais le serveur n'a pas réussi à la traiter.

500 Internal Server Error

Plantage générique du serveur. Quelque chose d'inattendu s'est produit.

En test : Si vous pouvez reproduire un 500 de façon fiable, c'est un bug, même si l'entrée était intentionnellement incorrecte. Une bonne conception d'API signifie que les entrées invalides retournent 4xx, pas 500. Quoi tester : une entrée invalide ne doit jamais produire un 500, mais un 400 ou 422. Les champs optionnels nuls ou manquants et les données aux cas limites (tableaux vides, chaînes très longues) ne doivent pas non plus planter le serveur.

502 Bad Gateway

Le serveur agissait comme passerelle/proxy et a reçu une mauvaise réponse d'un serveur en amont. Signifie souvent qu'une dépendance est en panne.

503 Service Unavailable

Le serveur est temporairement indisponible : surchargé ou en maintenance.

Pertinence pour les tests : Vérifiez comment le frontend gère un 503. Affiche-t-il une page d'erreur utile ? Réessaie-t-il intelligemment ? Dégrade-t-il gracieusement ?

504 Gateway Timeout

Similaire au 502 : une passerelle a expiré en attendant un serveur en amont. Apparaît souvent sous forte charge ou quand un service tiers est lent.

Tableau de référence rapide

| Code | Signification | Cause courante dans les bugs |

|------|--------------|------------------------------|

| 200 | OK | Retourné pour des créations qui devraient être 201 |

| 201 | Created | Manquant : l'API retourne 200 pour les POST |

| 204 | No Content | Body retourné alors qu'il ne devrait pas l'être |

| 301 | Permanent Redirect | Mauvais type de redirection |

| 304 | Not Modified | Cache périmé affichant des données obsolètes |

| 400 | Bad Request | Retourné pour des entrées valides-mais-incorrectes (devrait être 422) |

| 401 | Unauthorized | Manquant : vulnérabilité de contournement d'auth |

| 403 | Forbidden | Manquant : vulnérabilité de contournement d'autorisation |

| 404 | Not Found | 500 retourné pour des ressources manquantes à la place |

| 409 | Conflict | Manquant : doublons créés silencieusement |

| 422 | Unprocessable Entity | Confondu avec 400 |

| 429 | Too Many Requests | Manquant : attaque par force brute possible |

| 500 | Internal Server Error | Déclenché par une entrée invalide (devrait être 4xx) |

| 503 | Service Unavailable | Pas de dégradation gracieuse dans le frontend |

Tester les codes de statut avec Playwright

test('creating a user returns 201', async ({ request }) => {
  const response = await request.post('/api/users', {
    data: { email: 'new@test.com', password: 'ValidPass1' },
  });
  expect(response.status()).toBe(201);
});

test('duplicate email returns 409', async ({ request }) => {
  // Créer l'utilisateur d'abord
  await request.post('/api/users', {
    data: { email: 'existing@test.com', password: 'ValidPass1' },
  });
  // Réessayer avec le même e-mail
  const response = await request.post('/api/users', {
    data: { email: 'existing@test.com', password: 'ValidPass1' },
  });
  expect(response.status()).toBe(409);
});

test('missing token returns 401', async ({ request }) => {
  const response = await request.get('/api/profile');
  expect(response.status()).toBe(401);
});

test('wrong role returns 403', async ({ request }) => {
  // Utiliser un token membre, essayer d'accéder à un endpoint admin
  const response = await request.get('/api/admin/users', {
    headers: { Authorization: `Bearer ${memberToken}` },
  });
  expect(response.status()).toBe(403);
});

Les assertions sur les codes de statut sont les tests API les plus rapides et les plus fiables que vous puissiez écrire. Ils s'exécutent en millisecondes et détectent les bugs d'autorisation, les validations manquantes, et les conceptions d'API incorrectes.

→ See also: Tests d'API 101: Tout ce que Chaque Ingénieur QA Doit Savoir en 2026 | Qu'est-ce qu'une API REST? Un Guide Pratique pour les Ingénieurs QA | Tests d'API avec Playwright: Au-delà de l'Interface | Authentification dans les Tests d'API: Clés API, Tokens Bearer, OAuth2, JWT