Google classe 2 847 pages d'un e-commerce mode comme "soft 404" dans la Search Console. Le site renvoie pourtant un status code 200 sur chacune d'entre elles. Le trafic organique de ces pages tombe à zéro en trois semaines — sans qu'aucune alerte technique ne se déclenche côté serveur. C'est le scénario réel qui illustre pourquoi la distinction entre 404 et soft 404 n'est pas un détail académique, mais un enjeu opérationnel critique.
Anatomie d'un vrai 404 vs un soft 404
Le 404 classique : un contrat HTTP respecté
Un status code 404 signifie que le serveur a compris la requête mais que la ressource n'existe pas. Le contrat HTTP est clair : le client sait que la page est absente, Googlebot aussi. Le comportement attendu est simple — Google retire la page de l'index après quelques recrawls confirmant le 404.
Le problème n'est jamais le 404 en lui-même. Toute URL supprimée doit renvoyer un 404 (ou un 410 si la suppression est définitive). Google le confirme dans sa documentation sur les codes de status : un 404 est un signal sain quand il reflète une réalité.
Le soft 404 : un mensonge technique
Un soft 404, c'est une page qui dit "200 OK" au niveau HTTP mais dont le contenu signale une absence. Trois cas typiques :
- Page quasi-vide : un template e-commerce qui affiche "Aucun produit trouvé" avec le header, le footer, et un body de 200 octets utiles.
- Redirection vers la homepage : une fiche produit supprimée qui redirige silencieusement (via JavaScript, pas via 301) vers l'accueil.
- Page d'erreur custom sans status code : une belle page "Oups, cette page n'existe pas" servie avec un 200.
Google utilise des classifieurs basés sur le contenu de la page pour détecter ces cas. Le moteur compare le contenu rendu (après exécution JavaScript) à des patterns typiques de pages d'erreur. Quand il classifie une URL en soft 404, il la traite exactement comme un vrai 404 — sauf que vous ne le savez pas forcément, parce que votre monitoring serveur ne voit que des 200.
Pourquoi Google détecte des soft 404 là où vous n'en voyez pas
Le classifieur soft 404 de Google est agressif — parfois trop. Des pages légitimes avec peu de contenu (une catégorie avec 1 seul produit, une page de recherche interne avec peu de résultats) peuvent être classées soft 404. C'est un faux positif côté Google, mais l'impact sur l'indexation est identique.
Le rapport "Indexation des pages" de la Google Search Console est le seul endroit où ces classifications apparaissent. Si vous ne le consultez pas régulièrement, des centaines de pages peuvent disparaître de l'index sans que vos dashboards de monitoring HTTP ne bronchent.
L'impact concret sur le crawl budget et l'indexation
Scénario réel : migration de catalogue e-commerce
Prenez un site e-commerce spécialisé en équipement outdoor, 18 000 URLs indexées. En janvier, l'équipe produit désactive 3 200 références saisonnières. Le CMS ne supprime pas les pages — il vide le contenu produit et affiche "Ce produit n'est plus disponible" avec un status 200.
Voici la chronologie :
- Semaine 1-2 : Googlebot recrawle progressivement les 3 200 URLs. Status HTTP : 200 à chaque fois. Aucune alerte.
- Semaine 3 : Google Search Console commence à reporter des soft 404 par lots de 200-400 URLs par jour.
- Semaine 4-6 : les 3 200 pages sortent de l'index. Mais le problème ne s'arrête pas là.
- Semaine 6-8 : le crawl budget alloué au site diminue. Googlebot continue de recrawler les 3 200 URLs soft 404 (elles sont toujours dans le sitemap, toujours maillées en interne). Le crawl des nouvelles fiches produit printemps ralentit.
- Semaine 10 : le trafic organique global chute de 12%, bien au-delà de la perte attendue des seules pages désactivées.
Le coût réel du soft 404 n'est pas la perte de la page concernée — c'est la dilution du crawl et la perte de confiance du classifieur de qualité sur l'ensemble du domaine. Un site avec un ratio élevé de soft 404 envoie un signal de mauvaise maintenance à Google, ce qui peut affecter la fréquence de crawl globale.
Différence d'impact entre 404, 410 et soft 404
| Signal | Comportement Googlebot | Vitesse de désindexation | Impact crawl |
|---|---|---|---|
| 404 | Recrawle quelques fois puis abandonne | Quelques semaines | Modéré (crawl décroissant) |
| 410 | Abandonne plus rapidement | Quelques jours à 1-2 semaines | Minimal |
| Soft 404 (200) | Continue de crawler régulièrement | Quelques semaines à mois | Élevé (crawl gaspillé) |
Le 410 est le signal le plus propre pour une suppression définitive. Le vrai 404 est acceptable. Le soft 404 est le pire des trois parce qu'il combine une désindexation lente avec un gaspillage de crawl continu — Googlebot revient vérifier parce que le serveur lui dit encore "200 OK".
Détecter les soft 404 : méthodes et outillage
Google Search Console : la source de vérité
Le rapport Indexation des pages > Non indexées > Soft 404 est le point de départ. Exportez la liste complète des URLs concernées. Le piège : ce rapport est limité à 1 000 URLs dans l'interface. Pour un site avec des milliers de soft 404, utilisez l'URL Inspection API pour itérer sur vos URLs à grande échelle.
Voici un script Node.js qui interroge l'API pour détecter les URLs classées soft 404 dans un lot :
import { google } from 'googleapis';
const auth = new google.auth.GoogleAuth({
keyFile: 'service-account.json',
scopes: ['https://www.googleapis.com/auth/webmasters.readonly'],
});
const searchconsole = google.searchconsole({ version: 'v1', auth });
async function checkSoft404(urls: string[], siteUrl: string) {
const results: { url: string; verdict: string; coverageState: string }[] = [];
for (const url of urls) {
try {
const res = await searchconsole.urlInspection.index.inspect({
requestBody: {
inspectionUrl: url,
siteUrl,
},
});
const result = res.data.inspectionResult;
const state = result?.indexStatusResult?.coverageState || 'UNKNOWN';
const verdict = result?.indexStatusResult?.verdict || 'UNKNOWN';
if (state.includes('SOFT_404') || verdict === 'NEUTRAL') {
results.push({ url, verdict, coverageState: state });
}
// Respecter le rate limit de l'API : 2000 req/jour, 600 req/min
await new Promise(resolve => setTimeout(resolve, 150));
} catch (err) {
console.error(`Erreur pour ${url}:`, err);
}
}
return results;
}
// Usage
const urls = [
'https://outdoor-shop.fr/produit/veste-hiver-2024',
'https://outdoor-shop.fr/produit/gants-ski-pro',
// ... charger depuis votre sitemap ou BDD
];
checkSoft404(urls, 'https://outdoor-shop.fr').then(soft404s => {
console.log(`${soft404s.length} soft 404 détectés :`);
soft404s.forEach(s => console.log(` ${s.url} — ${s.coverageState}`));
});
Screaming Frog : détecter les candidats en amont
Screaming Frog ne détecte pas les soft 404 au sens Google du terme — il ne dispose pas du classifieur ML de Google. Mais vous pouvez configurer des filtres custom pour identifier les pages suspectes :
- Crawl complet > onglet Response Codes > filtrez les pages 200 avec un Word Count inférieur à 100 mots.
- Custom Search : cherchez les patterns textuels de vos pages d'erreur ("produit indisponible", "aucun résultat", "page introuvable") dans le body HTML.
- Configuration > Spider > cochez "Store HTML" pour pouvoir analyser le contenu rendu.
Pour les sites avec rendu JavaScript, activez le mode JavaScript Rendering dans Screaming Frog (Configuration > Spider > Rendering > JavaScript). Un site React ou Vue qui gère les 404 côté client ne renverra jamais un vrai 404 au serveur — c'est le cas typique de soft 404 sur les Single Page Applications.
Chrome DevTools : diagnostic unitaire
Pour une URL spécifique suspecte, ouvrez Chrome DevTools > onglet Network > rechargez la page. Vérifiez :
- Le status code de la requête document (première ligne).
- Le contenu du
<title>et du<meta name="robots">dans l'onglet Elements. - La taille du body : un document HTML de 5KB avec header/footer pour un contenu utile de 200 octets est un soft 404 typique.
Corriger les vrais soft 404 : code et configuration
Cas 1 : renvoyer un vrai 404 depuis le serveur
La correction la plus propre. Si la page n'a plus de contenu utile, renvoyez un vrai 404 (ou 410). Voici la configuration pour les cas courants :
Nginx — retourner un 410 pour des URLs de produits supprimés :
# Liste maintenue dans un fichier séparé, rechargeable sans restart
# Format du fichier : une URL par ligne
# /etc/nginx/conf.d/gone-products.map
map $request_uri $is_gone_product {
default 0;
include /etc/nginx/gone-products.list;
}
server {
listen 443 ssl;
server_name outdoor-shop.fr;
# Retourner 410 Gone pour les produits supprimés
if ($is_gone_product) {
return 410;
}
# Page d'erreur custom pour les 410
error_page 410 /gone.html;
location = /gone.html {
internal;
# Cette page doit être minimaliste et utile :
# lien vers les catégories principales, barre de recherche
}
# Idem pour les vrais 404
error_page 404 /404.html;
location = /404.html {
internal;
}
# ... reste de la config
}
Le fichier /etc/nginx/gone-products.list contient :
"/produit/veste-hiver-2024" 1;
"/produit/gants-ski-pro" 1;
"/produit/bonnet-laine-merinos-v2" 1;
L'avantage de map sur un bloc location par URL : vous gérez une liste de milliers d'URLs sans impacter les performances Nginx. La directive map est évaluée au moment de la requête, pas au chargement de la config.
Cas 2 : Next.js / Nuxt — retourner un 404 depuis le framework
Sur un site React/Next.js ou Vue/Nuxt, le soft 404 est endémique. Le serveur Node.js renvoie souvent 200 par défaut, même quand le composant affiche un message d'erreur.
Next.js — App Router (13+) :
// app/produit/[slug]/page.tsx
import { notFound } from 'next/navigation';
import { getProduct } from '@/lib/api';
interface Props {
params: { slug: string };
}
export default async function ProductPage({ params }: Props) {
const product = await getProduct(params.slug);
// Si le produit n'existe pas OU est désactivé → vrai 404
if (!product || product.status === 'discontinued') {
notFound(); // Renvoie un status 404 HTTP + affiche app/not-found.tsx
}
// Si le produit existe mais est temporairement indisponible → on l'affiche
// avec un message de stock, mais on garde le 200
// Nuance importante : "indisponible" ≠ "supprimé"
return (
<main>
<h1>{product.name}</h1>
{product.stock === 0 && (
<p>Temporairement en rupture de stock. Disponible sous 2-3 semaines.</p>
)}
{/* ... contenu produit complet */}
</main>
);
}
Le piège classique : traiter "rupture de stock" et "produit supprimé" de la même façon. Un produit en rupture doit garder sa page (200 OK) avec un contenu riche — description, avis, produits similaires. Un produit définitivement supprimé du catalogue doit renvoyer un 404 ou 410. La différence est critique pour Google : le premier reste indexable, le second non.
Cas 3 : rediriger plutôt que 404 — quand c'est justifié
Une redirection 301 est préférable au 404 quand une URL de remplacement existe. La fiche produit "Veste Trail V2" est remplacée par "Veste Trail V3" ? Redirigez. Mais ne redirigez pas toutes les pages supprimées vers la homepage — Google traite les redirections massives vers la homepage comme des soft 404.
La règle de décision :
- Équivalent direct → 301 vers la nouvelle URL
- Suppression définitive, pas d'équivalent → 410
- Suppression temporaire (saisonnier) → garder la page en 200 avec contenu réduit mais utile, ou 302 vers la catégorie parente
- Suppression sans certitude → 404 (Google reviendra vérifier)
Corriger les faux positifs soft 404 de Google
C'est le cas le plus frustrant : Google classe comme soft 404 des pages légitimes qui renvoient correctement un 200 et contiennent du contenu utile. Ce faux positif touche particulièrement :
- Les pages de catégorie avec très peu de produits (1-3 items)
- Les pages de listing filtrées avec peu de résultats
- Les pages dont le contenu principal est chargé en JavaScript après le rendu initial
- Les pages avec un ratio header/footer très élevé par rapport au contenu utile
Étoffer le contenu principal
Si une page catégorie affiche 2 produits et 800 pixels de header/footer pour 150 pixels de contenu utile, le classifieur Google peut la considérer comme vide. Solutions :
- Ajoutez une description de catégorie substantielle (200+ mots) au-dessus ou en dessous de la grille produits.
- Intégrez des liens vers les sous-catégories, des guides d'achat liés, des FAQ en schema JSON-LD.
- Assurez-vous que le contenu produit (titre, prix, description courte) est dans le HTML initial, pas injecté en lazy-load pur JS.
Vérifier le rendu JavaScript
Si votre contenu dépend de JavaScript, vérifiez ce que Google voit réellement. Utilisez l'outil d'inspection d'URL de la Search Console > "Tester l'URL en direct" > "Afficher la page testée" > onglet "HTML rendu".
Si le contenu principal n'apparaît pas dans le HTML rendu, Google ne le voit pas. C'est un problème de JavaScript et SEO distinct du soft 404, mais dont le symptôme est identique : Google considère la page comme vide.
Forcer le recrawl après correction
Une fois les corrections déployées, forcez un recrawl via l'API URL Inspection ou manuellement dans la Search Console. Le reclassement peut prendre 2 à 4 semaines. Ne supprimez pas les URLs corrigées de votre sitemap — au contraire, leur présence dans le sitemap confirme à Google que vous considérez ces pages comme valides.
Nettoyer le maillage interne et le sitemap
Les soft 404 et les vrais 404 qui persistent dans votre maillage interne et votre sitemap sont un signal de mauvaise hygiène technique. Chaque lien interne vers une page 404 gaspille du crawl budget et dilue le PageRank interne.
Auditer les liens internes cassés
Lancez un crawl Screaming Frog complet et exportez le rapport Response Codes > Client Error (4xx) > onglet Inlinks. Vous obtenez la liste de toutes les pages qui linkent vers des 404. Priorisez :
- Les pages avec le plus de trafic organique qui linkent vers des 404 (perte de PageRank maximale)
- Les templates qui génèrent des liens 404 sur des centaines de pages (sidebar "produits similaires" qui pointe vers des fiches supprimées)
- Les éléments de navigation globale (breadcrumb, menu) qui contiennent des 404
Nettoyer le sitemap
Votre sitemap ne doit contenir que des URLs qui renvoient un 200 et que vous souhaitez voir indexées. Un sitemap pollué de 404 et soft 404 est un signal négatif. Selon la documentation Google sur les sitemaps, inclure des URLs non canoniques ou en erreur dégrade la fiabilité du sitemap aux yeux du moteur.
Automatisez ce nettoyage. Si votre sitemap est généré dynamiquement (ce qui devrait être le cas), ajoutez un filtre qui exclut :
- Les produits avec status "discontinued" ou "supprimé"
- Les pages marquées
noindex - Les URLs qui redirigent (301/302)
Pour aller plus loin sur la gestion de l'index bloat lié à ces pages fantômes, la logique est la même : chaque URL inutile dans l'index est un frein.
Monitoring continu : ne plus subir les soft 404
Le problème fondamental des soft 404, c'est leur invisibilité. Vos logs serveur affichent des 200. Vos tests de smoke passent au vert. Seul Google sait qu'il considère la page comme vide — et il vous le dit avec un délai de plusieurs jours dans la Search Console.
Construire un système d'alerte proactif
L'approche idéale combine trois couches :
- Monitoring HTTP : vérifier que les pages supprimées renvoient bien un 404/410 (pas un 200). Testable avec un simple script curl en CI/CD.
- Monitoring du contenu : vérifier que les pages actives contiennent un volume de contenu suffisant après rendu JavaScript. Un check automatisé qui alerte quand le
innerTextdu<main>fait moins de 100 caractères. - Monitoring Search Console : suivre l'évolution du nombre de soft 404 reportés par Google et alerter en cas de pic.
Un outil de monitoring comme Seogard détecte automatiquement les régressions de status code — quand une page qui renvoyait un 200 hier passe en 404 ou inversement, quand le contenu principal d'une page tombe sous un seuil critique. Ce type de surveillance continue est la seule façon fiable de prévenir les incidents soft 404 avant qu'ils n'impactent l'indexation.
Intégrer les checks dans la CI/CD
Pour les équipes qui déploient fréquemment, ajoutez un test post-deploy qui vérifie un échantillon d'URLs critiques :
#!/bin/bash
# check-status-codes.sh — à exécuter en post-deploy
URLS=(
"https://outdoor-shop.fr/categorie/vestes"
"https://outdoor-shop.fr/produit/veste-trail-v3"
"https://outdoor-shop.fr/guide/choisir-sa-veste"
)
GONE_URLS=(
"https://outdoor-shop.fr/produit/veste-hiver-2024"
"https://outdoor-shop.fr/produit/gants-ski-pro"
)
EXIT_CODE=0
# Vérifier que les pages actives renvoient 200
for url in "${URLS[@]}"; do
status=$(curl -s -o /dev/null -w "%{http_code}" "$url")
if [ "$status" != "200" ]; then
echo "ERREUR: $url renvoie $status (attendu: 200)"
EXIT_CODE=1
fi
done
# Vérifier que les pages supprimées renvoient 410
for url in "${GONE_URLS[@]}"; do
status=$(curl -s -o /dev/null -w "%{http_code}" "$url")
if [ "$status" != "410" ]; then
echo "ERREUR: $url renvoie $status (attendu: 410)"
EXIT_CODE=1
fi
done
# Vérifier que la page 404 custom renvoie bien un 404
not_found_status=$(curl -s -o /dev/null -w "%{http_code}" "https://outdoor-shop.fr/cette-page-nexiste-pas-$(date +%s)")
if [ "$not_found_status" != "404" ]; then
echo "ERREUR: page inexistante renvoie $not_found_status (attendu: 404)"
EXIT_CODE=1
fi
exit $EXIT_CODE
Ce script basique attrape les régressions les plus courantes : une migration qui casse le routing, un middleware qui avale les 404, une config Nginx qui redirige tout vers l'accueil. Intégrez-le dans votre pipeline CI — un deploy qui transforme silencieusement des 404 en 200 (ou l'inverse) est un incident SEO.
Le vrai coût d'ignorer le problème
La distinction 404 / soft 404 semble technique et mineure jusqu'au jour où Google désindexe 15% de votre catalogue sans qu'aucune alerte ne se déclenche. Le soft 404 est un problème de contrat : votre serveur dit "tout va bien" alors que votre contenu dit "il n'y a rien ici". Google résout cette contradiction en vous ignorant.
La solution est systémique : des status codes honnêtes, un maillage interne propre, un sitemap qui reflète la réalité, et un monitoring qui surveille ce que Google voit — pas seulement ce que votre serveur renvoie. Seogard automatise cette couche de surveillance en comparant continuellement le comportement HTTP de vos pages avec leur statut d'indexation, pour que la prochaine vague de soft 404 soit détectée en heures, pas en semaines.