On a vu un LCP passer de 1,8 s à 4,2 s un lundi midi, sans mise en production. Le déclencheur : un article populaire sur un blog qui affichait l’image produit hébergée chez le propriétaire du site, en hotlinking direct. En vingt-quatre heures, le serveur a encaissé plus de 400 000 requêtes surnuméraires, toutes pour la même image. Résultat : une file d’attente côté back-end et un délai d’affichage qui explose pour les utilisateurs légitimes.
Ce n’est pas juste un vol de bande passante. C’est un goulot de performance qui frappe pile sur le Core Web Vital le plus sensible à la latence réseau : le Largest Contentful Paint. Et la plupart des rustines qu’on trouve en ligne aggravent le problème.
Le hotlinking tape directement dans le LCP
Chaque fois qu’un site externe embarque <img src="https://votredomaine.com/image.jpg">, le navigateur de son visiteur envoie une requête HTTP complète vers votre serveur. Votre serveur ouvre une connexion, charge l’image depuis le disque ou le cache, et la renvoie. Si ce site a du trafic, ça se traduit par une multiplication soudaine de requêtes concurrentes.
Votre serveur a une limite matérielle de workers et de descripteurs de fichiers. Quand une fraction croissante de cette capacité sert des images pour un tiers, les requêtes authentiques sont mises en file d’attente. Le TTFB grimpe, l’image LCP peut se retrouver bloquée derrière vingt hotlinks, et le LCP dépasse les 2,5 secondes. Et ce, sans aucun changement de code ni de contenu de votre côté.
Le piège classique consiste à ne surveiller que les métriques front-end de Web Vitals. On regarde Lighthouse, on accuse un bundle JS, et pendant ce temps la cause racine est dans les logs serveur.
Repérer les hotlinkeurs dans les logs serveur en cinq minutes
Une seule commande suffit, si vous avez accès aux logs bruts. Pour Apache ou Nginx, avec un format de log standard :
awk '{print $11}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -20
Ce pipeline extrait le champ Referer (souvent en position 11 dans un format combined), trie par fréquence et montre les vingt domaines qui génèrent le plus de requêtes vers vos ressources. Quand vous voyez apparaître un domaine qui n’est pas le vôtre, et qu’il pointe sur des URLs d’images, vous tenez le hotlinkeur.
Une alternative plus visuelle : dans la Search Console, le rapport sur les performances n’indique pas directement le hotlinking, mais si vous observez une hausse massive d’impressions pour des images sans clic correspondant sur votre site, c’est un indice. Les logs restent la source de vérité.
Les fausses bonnes idées qui explosent l’INP et le LCP
La réaction automatique de beaucoup de devs consiste à ajouter un bout de JavaScript :
if (document.referrer.indexOf('mondomaine.com') === -1) {
document.querySelectorAll('img').forEach(img => img.src = 'placeholder.jpg');
}
Ce code s’exécute côté client. Donc le navigateur du visiteur externe charge l’image réelle avant que le JS ne s’exécute et ne la remplace. Résultat : votre image est quand même téléchargée, la bande passante est consommée, et le hotlinkeur obtient un affichage éphémère de l’original avant de basculer sur un placeholder. Pire encore : cette vérification ajoute un décalage de layout, dégrade l’INP, et pour les vrais utilisateurs de votre site, elle injecte une tâche JavaScript au chargement.
L’autre fausse solution : rediriger les requêtes d’images vers une page d’erreur via une règle serveur qui renvoie une 301 ou 302. Le navigateur suit la redirection, interprète le contenu HTML reçu comme une image, et casse l’affichage chez le hotlinkeur certes, mais cette redirection consomme un aller-retour réseau supplémentaire et gonfle le TTFB pour les visiteurs légitimes si la règle est mal ciblée.
Le réflexe est le même qu’en state management React : une règle simple au bon endroit bat une cascade de conditions.
Blocage serveur sur le Referer : la couche qui ne touche pas au rendu
La seule approche qui ne coûte rien au temps de rendu s’effectue avant que le moindre octet ne quitte le serveur. On teste l’en-tête Referer de la requête entrante et on sert l’image uniquement si le domaine est autorisé ou absent (pour les accès directs). Exemple pour Nginx :
location ~* \.(png|jpg|jpeg|gif|webp|svg)$ {
valid_referers none blocked *.votredomaine.com;
if ($invalid_referer) {
return 403;
}
}
Le test du referer ne lit pas le corps de la requête, ne lance pas de sous-requête, ne dépend pas du JavaScript. Le serveur répond 403 en un temps quasi constant, sans charger le fichier image. Le navigateur du hotlinkeur reçoit un statut d’erreur et n’affiche rien ; votre serveur n’a pas ouvert l’image ni occupé un worker pour la servir. Conséquence directe sur le LCP : les requêtes légitimes ne subissent plus la concurrence des hotlinks.
Sur Apache, la syntaxe est différente, mais l’idée est identique : un RewriteCond %{HTTP_REFERER} couplé à RewriteRule renvoyant [F] pour interdire.
Cette règle n’interrompt pas le chargement des autres ressources, n’injecte pas de script, ne modifie pas le DOM. Elle reste invisible pour les utilisateurs légitimes du site.
Éviter le blocage de Googlebot et des partages sociaux
Le paramètre blocked derrière valid_referers autorise les requêtes sans referer. Or Googlebot, lorsqu’il explore vos images pour Google Images, envoie souvent un referer vide. Bloquer les referers vides, c’est effacer vos images des résultats de recherche. De même, certains agrégateurs, Pinterest, ou des messageries instantanées ne transmettent pas de referer pour des raisons de politique de confidentialité.
La règle doit donc absolument inclure none blocked. Si vous avez des CDN ou des sous-domaines de confiance, ajoutez-les explicitement. Et testez en passant le user-agent de Googlebot :
curl -I -H "Referer: https://site-tiers.com/" -H "User-Agent: Googlebot-Image/1.0" https://votredomaine.com/image.jpg
Si la réponse est 403 alors que le Referer est absent, votre règle est trop agressive.
On peut aussi prévoir une exception pour les réseaux sociaux dont on souhaite que l’image reste visible dans l’aperçu : ajouter *.facebook.com, *.twitter.com dans les referers valides si la stratégie de marque le demande. Mais chaque exception ajoutée complexifie la maintenance.
CDN et hotlinking : activer la protection sans impacter les Core Web Vitals
Si vos images passent par un CDN, la règle serveur seule ne suffit plus : le CDN peut servir la ressource depuis son cache sans jamais interroger votre origine pour les requêtes suivantes. Heureusement, la plupart des CDN (Cloudflare, BunnyCDN, KeyCDN) proposent un pare-feu de hotlinking configurable au niveau du layer edge, avec des listes de referers autorisés.
Activez cette option, mais surveillez le Cache-Control de vos images. Un blocage au niveau CDN renvoie aussi un statut 403 ou un redirect : si vous redirigez, vous ajoutez une latence. Privilégiez le blocage pur (403) qui sera lui-même mis en cache par le CDN, en limitant les allers-retours vers l’origine.
Pour générer ce type de règle, Claude Code et Cursor débroussaillent le terrain, mais une revue humaine reste obligatoire : un wildcard mal placé et vos images disparaissent des résultats Google.
Mesurer l’effet sur les Core Web Vitals après déploiement
Deux signaux après déploiement : P75 LCP dans la Search Console sur la semaine qui suit, et ratio 403/200 par referer dans les logs serveur. Sur un site qui saturait sur le hotlinking, le LCP baisse sans qu’on touche au front. Une brique de la stratégie d’optimisation des Core Web Vitals au même rang que le lazy-loading ou le fetch priority.
Questions fréquentes
Le hotlinking concerne-t-il uniquement les images ?
Non : les polices, les vidéos et même les PDF peuvent être hotlinkés. Pour les polices, le hotlinking alourdit les requêtes CORS et peut retarder le rendu du texte. Une règle Referer sur les fichiers statiques s’applique à tous les types MIME concernés.
Peut-on utiliser des en-têtes Content-Security-Policy contre le hotlinking ?
Non : la CSP ne bloque pas l’affichage d’une ressource sur un domaine tiers, elle restreint les sources depuis lesquelles un navigateur accepte de charger des contenus. C’est l’inverse. Le hotlinking est une attaque côté serveur, la protection est côté serveur.
Bloquer le hotlinking peut-il réduire le trafic de Google Images ?
Non, si le blocage autorise none et blocked. Googlebot se voit servir normalement l’image, et l’utilisateur qui clique arrive sur votre page, pas sur une version hotlinkée. La visibilité dans Google Images est préservée.