Le hotlinking consiste à afficher sur un autre site une image hébergée chez vous, en utilisant directement son URL. Résultat : le visiteur ne vient pas chez vous, mais votre serveur fournit quand même le fichier. Charmant. Vous payez la bande passante, l’autre site récupère l’image.
Sous Nginx, on peut limiter ce comportement avec le module ngx_http_referer_module. Il permet de vérifier l’en-tête HTTP Referer envoyé par le navigateur, puis de refuser les requêtes venant de domaines non autorisés.
Cette protection n’est pas parfaite. Un en-tête Referer peut être falsifié ou absent. En revanche, elle reste très utile pour bloquer le hotlinking classique : forums, blogs, agrégateurs douteux ou sites qui affichent vos images sans les héberger eux-mêmes.
Qu’est-ce que le hotlinking ?
Le hotlinking, aussi appelé liaison directe ou inline linking, désigne le fait d’utiliser directement l’URL d’un fichier hébergé sur un autre site.
Par exemple, un site externe peut afficher une image avec ce type de balise :
<img src="https://www.example.com/wp-content/uploads/photo.jpg" alt="">Langage du code : HTML, XML (xml)
Visuellement, l’image apparaît sur le site externe. Techniquement, elle est toujours servie par votre serveur. Si l’image devient populaire ailleurs, votre bande passante part en fumée sans vous apporter de trafic réel.
Pourquoi bloquer le hotlinking ?
Bloquer le hotlinking peut être utile pour plusieurs raisons.
- Réduire la consommation de bande passante.
- Éviter que des sites tiers utilisent vos images sans autorisation.
- Limiter les requêtes inutiles sur votre serveur.
- Protéger des fichiers médias lourds, comme les images originales ou certains documents.
- Réserver vos ressources à vos propres visiteurs.
Sur un petit site, le gain peut être modeste. Sur un site avec beaucoup d’images, de tutoriels, de captures d’écran ou de fichiers médias, cela peut vraiment soulager Nginx. C’est particulièrement vrai si vos images sont reprises par des forums, des scrapers ou des sites à fort trafic.
La méthode Nginx avec valid_referers
Nginx fournit la directive valid_referers. Elle définit les domaines autorisés à afficher vos fichiers. Quand le référent ne correspond pas, la variable $invalid_referer vaut 1. On peut alors retourner une erreur 403 Forbidden.
Voici une configuration simple pour protéger les images.
location ~* \.(?:gif|jpe?g|png|svg|webp|avif)$ {
valid_referers none blocked server_names
example.com
*.example.com
~\.google\.
~\.bing\.
~\.facebook\.
~\.pinterest\.;
if ( $invalid_referer ) {
return 403;
}
}Langage du code : PHP (php)
Remplacez évidemment example.com par votre domaine.
Pour SkyMinds, cela donnerait par exemple :
location ~* \.(?:gif|jpe?g|png|svg|webp|avif)$ {
valid_referers none blocked server_names
skyminds.net
*.skyminds.net
~\.google\.
~\.bing\.
~\.facebook\.
~\.pinterest\.;
if ( $invalid_referer ) {
return 403;
}
}Langage du code : PHP (php)
Cette règle autorise votre domaine, vos sous-domaines, les noms déclarés dans server_name, les requêtes sans référent, les référents masqués, ainsi que quelques plateformes utiles pour l’indexation, le partage ou la découverte d’images.
Votre hébergement est devenu un problème ?
Serveur partagé saturé, limites PHP trop basses, support qui répond en 48h — à un certain niveau de trafic, l'hébergement mutualisé devient le goulot. Je migre et configure des serveurs dédiés.
Parlons de votre infrastructure →Comprendre none, blocked et server_names
La directive valid_referers accepte plusieurs types de valeurs. Les trois plus fréquentes sont none, blocked et server_names.
| Valeur | Rôle | Faut-il l’utiliser ? |
|---|---|---|
none | Autorise les requêtes sans en-tête Referer | Oui, dans la plupart des cas |
blocked | Autorise les référents masqués par un proxy, pare-feu ou outil de confidentialité | Oui, souvent |
server_names | Autorise les noms définis dans la directive server_name | Oui, si votre server block est propre |
example.com | Autorise un domaine précis | Oui |
*.example.com | Autorise les sous-domaines | Oui, si nécessaire |
~\.google\. | Autorise via expression régulière | À utiliser avec parcimonie |
Ne soyez pas trop strict avec none. Certains navigateurs, extensions, réglages de confidentialité ou politiques Referrer-Policy peuvent supprimer l’en-tête Referer. Si vous bloquez toutes les requêtes sans référent, vous risquez de casser des affichages légitimes.
Où placer cette configuration ?
Placez cette règle dans le server block du site concerné, généralement dans un fichier comme :
/etc/nginx/sites-available/example.com
ou, selon votre organisation :
/etc/nginx/conf.d/example.com.conf
Sur un serveur qui héberge plusieurs sites, évitez de poser une règle globale dans nginx.conf sans réfléchir. Chaque domaine peut avoir ses propres besoins : CDN, sous-domaines médias, domaine statique, flux RSS, newsletters, réseaux sociaux, images Open Graph, etc.
Tester puis recharger Nginx
Avant de recharger Nginx, testez toujours la configuration.
sudo nginx -t
Si le test est correct, rechargez Nginx sans redémarrage complet.
sudo systemctl reload nginx
Évitez le vieux réflexe service nginx restart pour ce type de changement. Un reload suffit, et il est plus propre en production.
Tester la protection avec curl
Une fois la configuration rechargée, testez une image réelle.
Sans référent, la requête doit normalement passer si vous avez autorisé none.
curl -I https://www.example.com/wp-content/uploads/image.jpgLangage du code : JavaScript (javascript)
Avec un référent autorisé, la requête doit aussi passer.
curl -I \
-e https://www.example.com/article/ \
https://www.example.com/wp-content/uploads/image.jpgLangage du code : JavaScript (javascript)
Avec un référent externe non autorisé, Nginx doit retourner 403 Forbidden.
curl -I \
-e https://www.site-voleur.test/article/ \
https://www.example.com/wp-content/uploads/image.jpgLangage du code : JavaScript (javascript)
Vous devriez obtenir une réponse proche de celle-ci :
HTTP/2 403
server: nginxLangage du code : HTTP (http)
Si vous obtenez encore 200 OK, vérifiez l’ordre de vos blocs location. Une autre règle peut intercepter les images avant votre protection anti-hotlinking.
Attention à l’ordre des locations Nginx
Nginx sélectionne les blocs location selon des règles précises. Si vous avez déjà une règle pour les fichiers statiques, elle peut entrer en concurrence avec votre protection anti-hotlinking.
Par exemple, beaucoup de configurations WordPress contiennent déjà une règle de cache pour les assets :
location ~* \.(?:css|js|gif|jpe?g|png|svg|webp|avif|ico|woff2?)$ {
expires 30d;
add_header Cache-Control "public, max-age=2592000, immutable";
}Langage du code : JavaScript (javascript)
Dans ce cas, ne créez pas deux blocs concurrents pour les mêmes extensions. Fusionnez plutôt la protection anti-hotlinking dans le bloc d’images, ou séparez clairement les images des autres assets.
Voici une version plus propre pour WordPress, en protégeant seulement les images et en gardant le cache navigateur.
location ~* \.(?:gif|jpe?g|png|svg|webp|avif)$ {
valid_referers none blocked server_names
example.com
*.example.com
~\.google\.
~\.bing\.
~\.facebook\.
~\.pinterest\.;
if ( $invalid_referer ) {
return 403;
}
expires 30d;
add_header Cache-Control "public, max-age=2592000, immutable";
}Langage du code : PHP (php)
Faut-il protéger SVG, WebP et AVIF ?
Oui, si votre site utilise ces formats comme images publiques. Les anciens snippets se limitaient souvent à jpg, jpeg, png et gif. Aujourd’hui, il faut généralement inclure webp et avif.
Pour svg, tout dépend de votre usage. Si vous servez des icônes ou illustrations SVG publiques, vous pouvez l’inclure. Si vos SVG servent surtout d’assets de thème ou d’interface, vous pouvez aussi les gérer dans une règle séparée.
Variante : afficher une image anti-hotlinking
Au lieu de retourner un simple 403, vous pouvez rediriger les hotlinks vers une image dédiée. Par exemple une image légère indiquant que le hotlinking est interdit.
Je préfère généralement le 403, plus propre et moins consommateur. Mais si vous voulez une réponse visuelle, utilisez une redirection interne vers une image très légère.
location ~* \.(?:gif|jpe?g|png|svg|webp|avif)$ {
valid_referers none blocked server_names
example.com
*.example.com
~\.google\.
~\.bing\.
~\.facebook\.
~\.pinterest\.;
if ( $invalid_referer ) {
rewrite ^ /hotlink-denied.webp break;
}
expires 30d;
add_header Cache-Control "public, max-age=2592000, immutable";
}Langage du code : PHP (php)
Attention toutefois : servir une image de remplacement consomme encore une requête et un peu de bande passante. Pour bloquer proprement, return 403 reste souvent meilleur.
Variante CDN : Cloudflare, Bunny, Fastly, etc.
Si vos images passent par un CDN, vous pouvez aussi gérer le hotlinking au niveau du CDN. C’est parfois plus efficace, car la requête est bloquée avant d’atteindre votre serveur d’origine.
Dans ce cas, évitez les doublons incohérents. Si Cloudflare, Bunny ou Fastly bloque déjà certains référents, votre règle Nginx doit rester compatible avec le comportement du CDN. Sinon, vous risquez de diagnostiquer pendant une heure un problème causé par deux protections qui se marchent dessus. Grand classique, malheureusement.
Sur une configuration Cloudflare, pensez aussi à vérifier vos règles de cache, votre protection hotlink éventuelle, vos transformations d’images et vos domaines autorisés. L’origine Nginx ne voit pas toujours exactement la même chose que le navigateur final.
Cas WordPress : attention aux images Open Graph et aux flux
Sur WordPress, une protection trop stricte peut casser des usages légitimes.
- Prévisualisations Facebook, X, LinkedIn ou Mastodon.
- Images Open Graph utilisées dans les partages sociaux.
- Images reprises par Google Images ou Bing Images.
- Flux RSS affichés dans certains lecteurs.
- Newsletters qui embarquent vos images.
- Outils de monitoring ou de capture d’écran.
- CDN ou domaine statique dédié aux médias.
C’est pour cela que j’autorise généralement none et blocked, puis quelques domaines utiles. Une règle trop agressive peut sembler satisfaisante dans les logs, mais casser la diffusion normale de vos contenus. La sécurité qui vous sabote le SEO, c’est rarement une bonne affaire.
Exemple complet pour un site WordPress
Voici une version prête à adapter pour un site WordPress classique servi directement par Nginx.
server {
listen 443 ssl http2;
server_name example.com www.example.com;
root /var/www/example.com/public;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~* \.(?:gif|jpe?g|png|svg|webp|avif)$ {
valid_referers none blocked server_names
example.com
*.example.com
~\.google\.
~\.bing\.
~\.facebook\.
~\.pinterest\.
~\.linkedin\.
~\.x\.com
~\.twitter\.;
if ( $invalid_referer ) {
return 403;
}
expires 30d;
add_header Cache-Control "public, max-age=2592000, immutable";
access_log off;
log_not_found off;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}
}Langage du code : PHP (php)
Adaptez évidemment le domaine, le chemin root, la version PHP-FPM et les domaines à autoriser.
Surveiller les hotlinks dans les logs
Avant de bloquer, vous pouvez analyser vos logs Nginx pour repérer les domaines qui consomment vos images.
grep -Ei '\.(jpg|jpeg|png|gif|webp|avif|svg)' /var/log/nginx/access.log \
| awk -F\" '{print $4}' \
| sort \
| uniq -c \
| sort -nr \
| head -50Langage du code : JavaScript (javascript)
Cette commande extrait les référents les plus fréquents pour les requêtes d’images. Elle n’est pas parfaite, mais elle donne vite une idée des abus.
Pour suivre uniquement les erreurs 403 après activation, vous pouvez aussi filtrer les accès refusés selon votre format de logs.
grep ' 403 ' /var/log/nginx/access.log | tail -100Langage du code : JavaScript (javascript)
Les limites de cette protection
La protection anti-hotlinking par Referer est utile, mais elle a des limites importantes.
- Le référent peut être falsifié.
- Certains navigateurs n’envoient pas toujours de référent.
- Certains outils de confidentialité le suppriment.
- Un scraper avancé peut télécharger l’image puis la réhéberger.
- Une règle trop stricte peut bloquer des partages légitimes.
- Un CDN peut modifier le comportement attendu.
Il faut donc voir cette règle comme une barrière pragmatique, pas comme un coffre-fort. Elle réduit le hotlinking opportuniste. Elle ne remplace pas une stratégie complète si vous protégez des fichiers réellement sensibles.
Ce qu’il ne faut pas protéger avec cette méthode
N’utilisez pas cette technique pour protéger des fichiers privés, des documents payants ou des médias réservés à des membres. Le Referer n’est pas un mécanisme d’authentification.
Pour des fichiers vraiment privés, utilisez plutôt :
- une authentification applicative ;
- des URLs signées ;
- un contrôle d’accès côté application ;
X-Accel-Redirectavec Nginx ;- un stockage privé derrière un CDN compatible avec les liens signés.
Le hotlinking concerne surtout les ressources publiques que vous ne voulez pas servir gratuitement à tout Internet depuis des pages tierces.
Checklist avant mise en production
- Limiter la règle aux images, pas à tous les assets.
- Inclure les formats modernes :
webpetavif. - Autoriser votre domaine principal et vos sous-domaines utiles.
- Autoriser les moteurs et plateformes réellement nécessaires.
- Garder
nonesi vous ne voulez pas casser certains accès légitimes. - Tester avec
nginx -t. - Recharger avec
systemctl reload nginx. - Tester avec
curl -Iet un faux référent. - Surveiller les logs après activation.
- Vérifier les partages sociaux et les images Open Graph.
À retenir
- Le hotlinking consomme votre bande passante pour afficher vos images ailleurs.
- Nginx peut le limiter avec
valid_refererset$invalid_referer. - La règle doit être placée dans le bon
server blockou le bon bloclocation. - Un
return 403suffit généralement. - Il faut tester avec
curlavant de considérer la protection active. - La protection par
Refererbloque surtout les abus simples, pas les attaques sophistiquées.
Pour un site WordPress ou un blog riche en images, cette règle Nginx reste une bonne mesure d’hygiène serveur. Elle ne rend pas vos fichiers privés, mais elle évite que votre serveur devienne le garde-manger gratuit des sites qui préfèrent emprunter vos images plutôt que les héberger eux-mêmes.
Sources
- Documentation Nginx — ngx_http_referer_module
- Documentation Nginx — ngx_http_rewrite_module
- Documentation Nginx — Server names
- SkyMinds — Apache : supprimer le hotlinking
Votre hébergement est devenu un problème ?
Serveur partagé saturé, limites PHP trop basses, support qui répond en 48h — à un certain niveau de trafic, l'hébergement mutualisé devient le goulot. Je migre et configure des serveurs dédiés.
Parlons de votre infrastructure →

