Une page blanche, un 500 Internal Server Error, une API qui répond 401 sans raison apparente… Les codes HTTP sont le langage que ton serveur utilise pour te dire ce qui se passe. Dans ce guide, tu apprends à les lire, à trouver leur cause et à les corriger, avec des exemples concrets en PHP, Node.js et en ligne de commande.
Que tu développes un site, une API ou une application mobile, tu croises des codes HTTP tous les jours. Certains annoncent que tout va bien (200 OK), d’autres signalent un problème dans ta requête (404, 403, 422) ou sur le serveur (500, 502, 503). Bien les comprendre te fait gagner des heures de débogage et rend tes API beaucoup plus professionnelles.

Qu’est-ce qu’un code HTTP ?
Un code HTTP (ou code de statut) est un nombre à trois chiffres que le serveur renvoie au début de chaque réponse. Il résume le résultat de la requête : réussite, redirection ou erreur. Le navigateur, ton application ou un robot comme Googlebot s’en servent pour savoir quoi faire ensuite.
# Afficher uniquement les en-têtes de la réponse
curl -I https://lm-code.be/
HTTP/2 200
content-type: text/html; charset=UTF-8
cache-control: max-age=0, must-revalidateTerminalOuvre les outils de développement de ton navigateur (F12), onglet Réseau, puis recharge la page. La colonne « État » affiche le code HTTP de chaque fichier chargé. C’est le premier endroit à regarder quand quelque chose ne marche pas.
Les 5 familles de codes HTTP
Le premier chiffre suffit à savoir qui doit agir : le serveur, le navigateur ou toi.

Une erreur 4xx se corrige en changeant la requête (URL, jeton, données envoyées). Une erreur 5xx se corrige sur le serveur (code, configuration, base de données, ressources). Cette simple distinction t’évite de chercher au mauvais endroit.
Tableau des codes HTTP essentiels
Voici les codes que tu rencontreras le plus souvent, avec leur signification et l’endroit où chercher en cas de problème.
| Code | Nom | Signification | Où agir |
|---|---|---|---|
200 | OK | La requête a réussi. | — |
201 | Created | Une ressource a été créée (POST d’une API). | — |
204 | No Content | Réussite, sans contenu à renvoyer (souvent après un DELETE). | — |
301 | Moved Permanently | La page a définitivement changé d’adresse. | Redirections du serveur |
302 | Found | Redirection temporaire. | Redirections du serveur |
304 | Not Modified | La version en cache est encore valable. | Cache navigateur |
400 | Bad Request | Requête mal formée (JSON invalide, paramètre manquant). | Requête envoyée |
401 | Unauthorized | Authentification manquante ou invalide. | Jeton, session, identifiants |
403 | Forbidden | Authentifié, mais pas autorisé. | Droits, permissions |
404 | Not Found | La ressource n’existe pas à cette adresse. | URL, routes, fichiers |
405 | Method Not Allowed | Mauvaise méthode (GET au lieu de POST…). | Méthode HTTP, routes |
409 | Conflict | Conflit avec l’état actuel (doublon, version). | Données envoyées |
422 | Unprocessable Content | Format correct, mais données invalides. | Validation |
429 | Too Many Requests | Trop de requêtes en peu de temps. | Limitation de débit |
500 | Internal Server Error | Erreur inattendue dans le code ou la configuration. | Logs du serveur |
502 | Bad Gateway | Le proxy a reçu une réponse invalide du serveur d’application. | PHP-FPM, Node.js, proxy |
503 | Service Unavailable | Serveur surchargé ou en maintenance. | Ressources, maintenance |
504 | Gateway Timeout | Le serveur d’application a mis trop de temps à répondre. | Requêtes lentes, délais |
Les codes de succès et de redirection
200, 201 et 204 : choisir le bon succès
Dans une API REST, renvoyer toujours 200 fonctionne, mais ce n’est pas très parlant. Utilise 201 Created après une création (avec l’adresse de la nouvelle ressource) et 204 No Content après une suppression réussie.
// Création : 201 + la ressource créée
app.post('/api/articles', async (req, res) => {
const article = await Article.create(req.body);
res.status(201).location(`/api/articles/${article.id}`).json(article);
});
// Suppression : 204, sans corps de réponse
app.delete('/api/articles/:id', async (req, res) => {
await Article.destroy({ where: { id: req.params.id } });
res.sendStatus(204);
});routes/articles.js Express301 ou 302 : l’impact sur le SEO
Une redirection 301 indique à Google que la page a définitivement déménagé : il transfère le référencement vers la nouvelle adresse. Une 302 est temporaire et ne transfère rien. Quand tu changes l’URL d’un article, utilise toujours une 301.
# Redirection permanente d'une ancienne adresse vers la nouvelle
Redirect 301 /ancien-article/ https://monsite.be/nouvel-article/
# Forcer le HTTPS sur tout le site
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L].htaccess304 Not Modified : le cache qui fait gagner du temps
Quand le navigateur possède déjà une copie d’un fichier, il demande au serveur s’il a changé (en-têtes If-None-Match ou If-Modified-Since). Si ce n’est pas le cas, le serveur répond 304 sans renvoyer le fichier : la page se charge plus vite et consomme moins de bande passante. Ce n’est donc pas une erreur.
Les erreurs client 4xx : causes et solutions
400 Bad Request
Le serveur ne comprend pas la requête. Causes fréquentes : JSON mal formé (virgule en trop, guillemets simples), en-tête Content-Type absent, paramètre obligatoire manquant, cookie ou URL trop longs.
- Vérifie le corps de la requête dans l’onglet Réseau (Payload).
- Envoie bien
Content-Type: application/jsonquand tu envoies du JSON. - Si l’erreur n’arrive que sur ton navigateur, supprime les cookies du site : un cookie corrompu ou trop volumineux suffit à provoquer un 400.
# Requête JSON correcte avec curl
curl -X POST https://api.exemple.be/articles \
-H "Content-Type: application/json" \
-d '{"titre": "Mon article", "publie": true}'Terminal401 Unauthorized et 403 Forbidden
On les confond souvent. 401 signifie « je ne sais pas qui tu es » : jeton absent, expiré ou mal envoyé. 403 signifie « je sais qui tu es, mais tu n’as pas le droit » : rôle insuffisant, permissions de fichier, règle de pare-feu.
- 401 : vérifie l’en-tête
Authorization: Bearer …, la date d’expiration du jeton et la session. - 403 : vérifie le rôle de l’utilisateur, les permissions des fichiers (644 pour les fichiers, 755 pour les dossiers) et les règles du pare-feu (Wordfence, Cloudflare, ModSecurity).
404 Not Found
La ressource n’existe pas à cette adresse : faute de frappe, page supprimée, route mal déclarée ou fichier absent. Sur WordPress, un 404 sur tous les articles vient souvent des permaliens : Réglages → Permaliens → Enregistrer régénère les règles de réécriture.
Une page supprimée qui avait du trafic doit être redirigée en 301 vers le contenu le plus proche. Laisser des centaines de 404 dans la Search Console fait perdre des visiteurs et du référencement.
405, 409 et 422 : les erreurs d’API
405 : la route existe, mais pas pour cette méthode (un formulaire envoyé en GET vers une route POST). 409 : conflit avec l’état actuel, par exemple une adresse e-mail déjà utilisée. 422 : le JSON est valide, mais les données ne respectent pas tes règles de validation.
<?php
header('Content-Type: application/json; charset=utf-8');
$donnees = json_decode(file_get_contents('php://input'), true);
if ($donnees === null) {
http_response_code(400); // JSON illisible
echo json_encode(['erreur' => 'JSON invalide']);
exit;
}
if (!filter_var($donnees['email'] ?? '', FILTER_VALIDATE_EMAIL)) {
http_response_code(422); // Données invalides
echo json_encode(['erreur' => 'Adresse e-mail invalide']);
exit;
}
if (emailExisteDeja($donnees['email'])) {
http_response_code(409); // Conflit
echo json_encode(['erreur' => 'Cette adresse est déjà utilisée']);
exit;
}
http_response_code(201);
echo json_encode(['message' => 'Compte créé']);api/inscription.php429 Too Many Requests
Tu as dépassé la limite de requêtes autorisée (API externe, protection anti-robots, pare-feu). Respecte l’en-tête Retry-After s’il est présent, espace tes appels et mets les réponses en cache. Côté serveur, c’est le bon code à renvoyer pour limiter les abus sur une page de connexion.
Les erreurs serveur 5xx : causes et solutions
Avec une erreur 5xx, ta requête n’y est pour rien : c’est le serveur qui a échoué. La réponse se trouve presque toujours dans les journaux (logs), pas dans le navigateur.
500 Internal Server Error
C’est l’erreur « fourre-tout » : une exception non gérée, une erreur de syntaxe PHP, un .htaccess invalide, une limite de mémoire dépassée ou une connexion à la base de données impossible.
- Lis le log d’erreurs du serveur ou de PHP : la ligne exacte du problème y est indiquée.
- Sur WordPress, active temporairement le mode débogage (ci-dessous), puis désactive les extensions une par une si l’erreur vient d’un plugin.
- Renomme le fichier
.htaccesspour tester s’il est en cause. - Augmente
memory_limitsi le log parle de « Allowed memory size exhausted ».
// Enregistre les erreurs dans wp-content/debug.log sans les afficher aux visiteurs
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );wp-config.phpUne fois le problème trouvé, repasse WP_DEBUG à false et supprime le fichier debug.log : il peut contenir des chemins, des requêtes SQL ou des informations sensibles. En production, n’affiche jamais les erreurs détaillées aux visiteurs.
# Suivre les erreurs en direct (serveur Linux)
tail -f /var/log/nginx/error.log
tail -f /var/log/apache2/error.log
# Erreurs d'une application Node.js gérée par PM2
pm2 logs mon-app --lines 100Terminal502 Bad Gateway
Le serveur web (Nginx, Apache, Cloudflare) fonctionne, mais l’application derrière lui ne répond pas correctement : PHP-FPM arrêté ou saturé, application Node.js plantée, mauvais port dans la configuration du proxy.
- Vérifie que le service tourne :
systemctl status php8.3-fpmoupm2 status. - Contrôle que le port ou le socket configuré dans Nginx correspond à celui de l’application.
- Redémarre le service et surveille les logs pour voir s’il replante.
503 Service Unavailable
Le serveur est temporairement indisponible : surcharge, maintenance, limite de ressources de l’hébergement atteinte. Sur WordPress, un fichier .maintenance oublié après une mise à jour interrompue bloque tout le site en 503 : supprime-le à la racine. Pour une vraie maintenance, renvoie un 503 avec un en-tête Retry-After : Google comprend que c’est temporaire et ne pénalise pas le site.
504 Gateway Timeout
L’application met trop de temps à répondre et le proxy abandonne. Causes typiques : requête SQL lente, appel à une API externe qui ne répond pas, traitement lourd (import, génération de PDF) exécuté pendant la requête.
- Repère la requête lente (journal des requêtes lentes de MySQL, outil comme Query Monitor sur WordPress).
- Ajoute des index sur les colonnes utilisées dans les
WHEREet les jointures. - Déplace les traitements longs dans une tâche de fond (file d’attente, tâche cron).
- En dernier recours seulement, augmente les délais (
proxy_read_timeout,max_execution_time).
Méthode pour diagnostiquer n’importe quel code HTTP

- Lire le code exact dans l’onglet Réseau ou avec
curl -I. Un « ça ne marche pas » n’est pas un diagnostic, un502en est un. - Identifier le côté : 4xx, regarde la requête ; 5xx, regarde le serveur.
- Lire les logs du serveur web, de PHP ou de ton application. Le message d’erreur précis s’y trouve presque toujours.
- Reproduire, corriger et re-tester, puis vérifier que le bon code est renvoyé.
Bonnes pratiques pour une API professionnelle
- Renvoie le code qui correspond vraiment à la situation : jamais un
200avec{"erreur": …}dans le corps. - Accompagne chaque erreur d’un message JSON clair et stable, utile au développeur qui consomme ton API.
- Ne révèle jamais de détails internes (requête SQL, chemin de fichier, trace complète) dans une réponse publique.
- Utilise
401pour l’authentification et403pour les droits, sans les mélanger. - Documente les codes possibles pour chaque route de ton API.
// Gestionnaire d'erreurs centralisé : un format unique pour toute l'API
app.use((err, req, res, next) => {
const status = err.status ?? 500;
if (status >= 500) console.error(err); // détails dans les logs uniquement
res.status(status).json({
erreur: status >= 500 ? 'Erreur interne du serveur' : err.message,
});
});middleware/erreurs.js ExpressPour mettre ces bonnes pratiques en œuvre sur un vrai projet, regarde notre application de gestion de stock en PHP et MySQL ou notre projet MediaCloud avec une API Express, qui renvoie des codes HTTP précis pour chaque situation. Pour tester un serveur en local sans risque, suis notre guide WordPress en local avec Docker.
Pour aller plus loin, la documentation de référence est celle de MDN sur les codes de statut HTTP.
FAQ
Quelle est la différence entre une erreur 4xx et 5xx ?
Une erreur 4xx vient de la requête (mauvaise URL, droits manquants, données invalides) et se corrige côté client. Une erreur 5xx vient du serveur (code, configuration, ressources) et se corrige côté serveur, en lisant les logs.
Comment corriger une erreur 500 sur WordPress ?
Active le mode débogage dans wp-config.php avec WP_DEBUG_LOG, lis le fichier debug.log, puis désactive les extensions une par une ou renomme le fichier .htaccess pour isoler la cause. Pense à désactiver le débogage ensuite.
Une erreur 304 est-elle grave ?
Non. Le code 304 Not Modified signifie que le navigateur peut utiliser sa copie en cache. C’est une optimisation, pas une erreur.
Faut-il utiliser une redirection 301 ou 302 ?
Utilise une 301 quand le changement d’adresse est définitif : Google transfère le référencement vers la nouvelle page. La 302 est réservée aux redirections temporaires.
Quelle différence entre 401 et 403 ?
Le code 401 signifie que l’utilisateur n’est pas authentifié (jeton absent ou expiré). Le code 403 signifie qu’il est authentifié mais n’a pas le droit d’accéder à la ressource.
Comment voir le code HTTP d’une page ?
Ouvre les outils de développement avec F12, onglet Réseau, puis recharge la page. Tu peux aussi utiliser la commande curl -I suivie de l’adresse de la page.
Conclusion
Les codes HTTP ne sont pas des messages cryptiques : ils te disent exactement où chercher. Retiens le premier chiffre pour savoir qui doit agir, lis toujours les logs pour les erreurs 5xx, et renvoie des codes précis dans tes propres API. Tu passeras moins de temps à déboguer, et tes projets auront l’air beaucoup plus professionnels.

