PRIVACIDAD

Tus preferencias.

Rechazar no limita el acceso a la web. Cerrar sin guardar conserva tu decisión anterior.

Técnicas · siempre activas

Guardamos únicamente tu elección durante un máximo de 12 meses en este navegador.

Consultar proveedores, duración y transferencias

Rastreo

X-Robots-Tag: qué es y cómo usarlo en Apache, Nginx y PHP

La cabecera HTTP que hace de meta robots para PDF e imágenes: directivas que soporta Google, configuración por servidor y el error de bloquearla con robots.txt.

¿Quieres aplicarlo a tu web?Hablemos
ResumenQué es X-Robots-Tag y en qué se diferencia de la meta robots
Puntos clave
  • X-Robots-Tag es una cabecera HTTP que da a Google las mismas instrucciones de indexación que la etiqueta meta robots, y es la única opción para PDF, imágenes y otros archivos que no son HTML.
  • Google documenta estas directivas: all, noindex, nofollow, none, nosnippet, indexifembedded, max-snippet, max-image-preview, max-video-preview, notranslate, noimageindex y unavailable_after.
  • Si dos reglas chocan, Google aplica la más restrictiva. Con max-snippet:50 y nosnippet, gana nosnippet.
  • Si la URL está bloqueada en robots.txt, Google no puede rastrearla y no llega a leer la cabecera: el noindex no se aplica.
  • En Apache necesitas mod_headers; en Nginx, add_header con always y cuidado con la herencia entre bloques; en PHP, header() antes de cualquier salida.
  • Se verifica con curl -I primero y con la Inspección de URL de Search Console después.

Un PDF con la tarifa de hace dos años sigue saliendo en Google y no hay ninguna etiqueta que ponerle: un PDF no tiene <head>. Lo mismo pasa con un fichero de descarga interno o una imagen que no quieres ver en Google Imágenes. Para eso existe X-Robots-Tag, una cabecera de la respuesta HTTP que transmite las mismas instrucciones que la meta robots.

Aquí cubro qué directivas acepta Google según su documentación, cómo se escribe con un user-agent concreto, cómo se implementa en Apache, Nginx y PHP, qué pasa cuando dos reglas se contradicen, por qué bloquear en robots.txt la deja inservible y cómo comprobar que funciona. También cuento cómo uso yo la cabecera en este sitio, incluida una incoherencia que he encontrado al revisarlo.

Dos columnas: la meta robots viaja dentro del HTML de una página y la cabecera X-Robots-Tag viaja en la respuesta HTTP de un PDF o una imagen.
La misma instrucción por dos vías: dentro del HTML (meta robots) o en la respuesta HTTP (X-Robots-Tag).

Qué es X-Robots-Tag y en qué se diferencia de la meta robots

Cuando un rastreador pide una URL, el servidor responde con una línea de estado, una serie de cabeceras y, después, el cuerpo. X-Robots-Tag es una de esas cabeceras. Según la documentación de Google sobre las especificaciones de robots meta, sirve para archivos que no son HTML, como imágenes o PDF, donde no se puede insertar una etiqueta meta.

La etiqueta <meta name="robots" content="noindex"> y la cabecera X-Robots-Tag: noindex expresan lo mismo. Cambia el canal, y con él lo que puedes hacer.

AspectoMeta robotsX-Robots-Tag
Dónde vaDentro del <head> del HTMLEn la cabecera de la respuesta HTTP
Tipos de archivoSolo páginas HTMLCualquiera: HTML, PDF, imágenes, vídeo, JSON, XML
Dónde se configuraPlantilla, CMS o pluginServidor web, CDN o código de la aplicación
Aplicación en bloquePágina a páginaPor patrón: todos los .pdf, toda una carpeta
Visible en el código fuenteSíNo: solo en las cabeceras de la respuesta

La segunda ventaja, aplicar una regla a muchas URLs a la vez, es la que más pesa en sitios grandes: un patrón en el servidor cubre todos los PDF de una vez, mientras que revisarlos uno a uno es inviable. En una página HTML normal prefiero la meta robots, porque queda a la vista en el código fuente y cualquiera del equipo la encuentra al revisar la plantilla.

Cuándo tiene sentido usar la cabecera

Estos son los casos en los que la cabecera es la herramienta correcta, no una opción más.

  • PDF y documentos de Office que no deben competir con la página que los enlaza: fichas técnicas duplicadas, tarifas caducadas, contratos o formularios de descarga. Si el PDF duplica una página HTML, también puedes señalar el original con una cabecera canonical en lugar de excluirlo.
  • Imágenes que no quieres en Google Imágenes, con noindex aplicado a una carpeta o a una extensión. Para las que sí quieres posicionar, mira cómo optimizar las imágenes para SEO.
  • Respuestas que no son páginas: endpoints JSON, feeds internos, resultados de buscador interno.
  • Entornos de staging, donde una regla global a nivel de servidor evita tocar cada plantilla (aunque en staging la protección con contraseña es más segura que cualquier directiva).
  • Contenido con fecha de caducidad, con unavailable_after, cuando sabes de antemano cuándo deja de tener sentido.

Si el archivo es HTML y puedes editar su plantilla, la meta robots hace lo mismo con menos riesgo de que una regla de servidor afecte a más URLs de las previstas.

Directivas que soporta Google

La documentación de Google lista las directivas que se pueden usar en la meta robots y en la cabecera. Se pueden combinar separadas por comas y no distinguen mayúsculas de minúsculas. Esta es la lista tal y como aparece en su especificación.

Cinco cuadros con las doce directivas de Google agrupadas: indexación, enlaces, caducidad, fragmentos y medios, e idioma e imágenes.
Las directivas de Google agrupadas por lo que controlan.
DirectivaQué hace
allSin restricciones. Es el valor por defecto.
noindexNo muestra la página en los resultados.
nofollowNo sigue los enlaces de la página.
noneEquivale a noindex, nofollow.
nosnippetNo muestra fragmento de texto ni vista previa de vídeo.
indexifembeddedPermite indexar el contenido cuando se incrusta en otra página (iframe o similar), aunque tenga noindex. Solo tiene efecto junto a noindex.
max-snippet:[n]Límite de caracteres del fragmento. 0 equivale a nosnippet; -1 no fija límite.
max-image-preview:[ajuste]Tamaño máximo de la imagen en vista previa: none, standard o large.
max-video-preview:[n]Segundos máximos de la vista previa de vídeo.
notranslateNo ofrece traducción de la página en los resultados.
noimageindexNo indexa las imágenes de la página.
unavailable_after:[fecha]Deja de mostrar la página después de la fecha indicada.

noarchive circula en muchas guías, pero no aparece en la lista de la especificación que he leído para este artículo, así que no lo trato como directiva soportada por Google.

unavailable_after: el formato de fecha

Google pide una fecha y hora en un formato ampliamente adoptado y menciona RFC 822, RFC 850 e ISO 8601. Su ejemplo es unavailable_after: 25 Jun 2010 15:00:00 PST. Si la fecha no es válida, la regla se ignora, y sin esta regla el contenido no tiene fecha de caducidad. Mi consejo es escribir la fecha con zona horaria explícita y comprobar la cabecera con curl: un error de formato no da ningún aviso, simplemente no ocurre nada.

La documentación tampoco detalla cuánto tarda en aplicarse. Solo indica que, pasada la fecha, Googlebot reduce considerablemente la frecuencia de rastreo de esa URL. No hay un plazo documentado.

Sintaxis: varias reglas y user-agent concreto

La forma básica es una cabecera con una lista separada por comas, que se aplica a todos los rastreadores:

X-Robots-Tag: noindex, nofollow

Google acepta también varias cabeceras X-Robots-Tag en la misma respuesta, y se combinan. Para dirigir una regla a un rastreador concreto, se antepone su nombre seguido de dos puntos. El ejemplo de la documentación:

X-Robots-Tag: googlebot: nofollow
X-Robots-Tag: otherbot: noindex, nofollow

Las reglas sin user-agent valen para todos los rastreadores. El nombre de la cabecera, el user-agent y los valores no distinguen mayúsculas. Un uso real: X-Robots-Tag: googlebot: noindex para que Google no indexe un recurso y otros buscadores sí. No hace falta salvo que tengas un motivo claro; en el resto de casos, una regla general es más fácil de mantener.

Un detalle práctico: este valor depende de que el rastreador entienda la cabecera. La especificación que cito es la de Google. Para otros buscadores, comprueba su propia documentación antes de asumir que soportan las mismas directivas.

Implementación en Apache con .htaccess

En Apache la cabecera se añade con la directiva Header del módulo mod_headers, que debe estar cargado. En un .htaccess funciona si el servidor permite AllowOverride FileInfo, según la documentación de Apache. Un patrón con FilesMatch y una expresión regular cubre todas las extensiones que necesites:

Tres bloques de código con la misma cabecera noindex: FilesMatch con Header set en Apache, location con add_header en Nginx y header() en PHP.
La misma cabecera escrita en Apache, Nginx y PHP, con el requisito principal de cada una.
<IfModule mod_headers.c>
  <FilesMatch "\.(pdf|docx?|xlsx?)$">
    Header set X-Robots-Tag "noindex, nofollow"
  </FilesMatch>
</IfModule>

El ejemplo de la documentación de Google usa <Files ~ "\.pdf$"> con la misma idea. Tres detalles que he visto fallar:

  • El punto va escapado (\.). Sin escapar, .pdf$ coincide con cualquier carácter antes de pdf.
  • La expresión distingue mayúsculas. Un Informe.PDF no encaja con \.pdf$; añade (?i) al principio si hay extensiones en mayúsculas.
  • Sin condición, Header set actúa sobre las respuestas 2xx. Para que se añada también en errores, la documentación de Apache indica la condición always: Header always set X-Robots-Tag "noindex".

Una carpeta entera

Para toda una carpeta, coloca un .htaccess dentro de ella con Header set X-Robots-Tag "noindex, nofollow", o usa un bloque <Directory> o <Location> en la configuración del servidor si tienes acceso. Para los ficheros PDF de una ruta, FilesMatch dentro de ese .htaccess es suficiente.

Implementación en Nginx

En Nginx se usa add_header dentro de un bloque location. Es el ejemplo que da Google, con la misma lógica que en Apache:

location ~* \.(pdf|docx?|xlsx?)$ {
    add_header X-Robots-Tag "noindex, nofollow" always;
}

Dos reglas de la documentación de Nginx evitan los problemas más comunes:

  • always: sin este parámetro, la cabecera solo se añade en las respuestas con código 200, 201, 204, 206, 301, 302, 303, 304, 307 o 308. Con always, se añade con cualquier código.
  • Herencia: los add_header de un nivel se heredan al siguiente solo si el nivel actual no define ninguno propio. Si añades un add_header en un location que ya tenía otros definidos en el server, los del server dejan de aplicarse ahí. Es la razón por la que a veces desaparecen cabeceras de seguridad al añadir una de SEO.

Tras cada cambio, recarga la configuración (nginx -s reload) después de validarla con nginx -t.

Implementación en PHP

Cuando la respuesta la genera tu código, lo más simple es enviar la cabecera desde ahí con header():

<?php
header('X-Robots-Tag: noindex, nofollow');
// resto de la respuesta

Según el manual de PHP, header() debe llamarse antes de enviar cualquier contenido, y un espacio o una línea en blanco antes de la etiqueta <?php en un include basta para romperlo; en ese caso PHP emite un E_WARNING. Además, por defecto header() reemplaza una cabecera anterior del mismo nombre: si quieres enviar varias X-Robots-Tag, pasa false como segundo parámetro. En un CMS o un framework conviene hacerlo en el punto donde se prepara la respuesta, no en una plantilla ya renderizada.

Este método es el que cubre los casos dinámicos que ni Apache ni Nginx ven con un patrón: un listado filtrado, una respuesta de error personalizada o un endpoint JSON.

Qué pasa cuando las reglas chocan

Las reglas pueden llegar de varios sitios a la vez: una meta robots en el HTML, una o varias cabeceras del servidor, otra que añade un plugin o la CDN. La documentación de Google lo resuelve así: ante reglas en conflicto, se aplica la más restrictiva. Su ejemplo: si una página tiene max-snippet:50 y nosnippet, se aplica nosnippet.

Tres ejemplos de reglas en conflicto, cada uno con las dos reglas de entrada y la que se aplica: noindex gana a index, nosnippet gana a max-snippet:50.
Si una regla permite y otra restringe, vale la restrictiva.

En la práctica significa dos cosas. La primera: no puedes anular un noindex de la cabecera poniendo index en la meta robots; la cabecera seguirá mandando. La segunda: un noindex heredado de un entorno de staging, una regla genérica de servidor o una opción de un plugin puede seguir activo sin que lo veas en el HTML. Por eso, cuando una página no se indexa y su meta robots parece limpia, miro las cabeceras antes que nada.

Si una URL no se indexa y en el código fuente no hay ningún noindex, ejecuta curl -I contra ella. La cabecera no aparece en el código fuente y es un sitio donde suele esconderse un noindex que nadie puso a propósito.

La trampa: bloquear en robots.txt y esperar que funcione el noindex

Es un error muy repetido. Alguien quiere sacar de Google un conjunto de PDF, pone noindex en la cabecera y, por si acaso, añade un Disallow en robots.txt. El Disallow anula la cabecera.

La cabecera solo se lee si Google pide la URL. Si robots.txt se lo impide, Google no recibe la respuesta, no ve la cabecera y el noindex no se aplica. La documentación de Google lo dice de forma explícita: si las reglas de indexación o de servido deben cumplirse, las URLs que las contienen no pueden estar bloqueadas para el rastreo. Y una URL bloqueada puede seguir apareciendo en los resultados, sin descripción, si otras páginas la enlazan.

Dos flujos: con Disallow en robots.txt, Googlebot se detiene antes de pedir la URL y no ve la cabecera noindex; sin Disallow, Googlebot pide la URL, lee la cabecera y la excluye.
Con el Disallow, Googlebot no llega a pedir la URL. Sin él, lee la cabecera y excluye el archivo.

El orden correcto es dejar la URL rastreable con su noindex, esperar a que Google la procese y, solo entonces, si hace falta ahorrar rastreo, valorar el bloqueo. Para el detalle de cómo funcionan los bloqueos, lo cuento en el artículo sobre robots.txt.

Esto enlaza con otra confusión: X-Robots-Tag controla indexación y servido, no rastreo. Google rastrea la URL para leer la cabecera, así que tampoco ahorra presupuesto de rastreo. Si el objetivo es solo recortar fragmentos en lugar de excluir la página, las directivas nosnippet y max-snippet hacen eso, y para un trozo concreto del texto tienes data-nosnippet.

Cómo la uso en mi web

Lo que sigue sale de leer el código de este sitio, no de lo que me gustaría tener. El uso real de X-Robots-Tag es pequeño y siempre desde PHP:

ArchivoCabeceraPara qué
send.phpnoindex, nofollowProcesa el formulario de contacto. No es una página para el buscador.
404.phpnoindex, nofollowPágina de error. Responde con 404 real y, además, lleva meta robots noindex, nofollow en el HTML.
blog/feed.phpnoindexRespuesta JSON que carga el listado del blog. No es contenido indexable.
includes/article-page.phpnoindexSolo en un caso: el artículo no existe, no está publicado o le falta el cuerpo (devuelve 404).
blog/google-io-2025/index.phpnoindexArtículo retirado: responde con 410 y un aviso de que se ha retirado.
Lista de cinco archivos PHP de mi sitio que envían X-Robots-Tag noindex, con una nota sobre la incoherencia de send.php y otra sobre feed.php bien resuelto.
Los cinco puntos donde envío la cabecera y las dos observaciones de la auditoría.

Todo lo demás lleva la etiqueta meta en el HTML. La plantilla includes/header.php imprime por defecto index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1, y el listado del blog cambia a noindex, follow cuando hay un filtro de categoría o una búsqueda. Esa es la razón por la que esas URLs no usan cabecera: son HTML y puedo controlarlas desde la plantilla.

Lo que no tengo: ninguna regla de X-Robots-Tag en el .htaccess. Hoy no hay ningún PDF en el sitio, así que no he necesitado un FilesMatch. El .htaccess sí usa Header always set para otras cabeceras (X-Content-Type-Options, Referrer-Policy y X-Frame-Options), y de ahí saldría el patrón si tuviera que sumar uno.

Dos incoherencias que he encontrado al revisarlo

La primera es justo la trampa de la sección anterior. send.php envía X-Robots-Tag: noindex, nofollow, pero mi robots.txt tiene Disallow: /send.php. Con el Disallow, Googlebot no pide esa URL y la cabecera nunca llega a leerse. Aquí no tiene consecuencias prácticas, porque un GET a send.php sin un envío previo devuelve 405 con el mensaje «Envía tu consulta desde el formulario de la web» y no hay contenido que indexar. Pero la cabecera, tal como está, no cumple función ante Google. Si quisiera que la regla fuera efectiva, tendría que quitar el Disallow, o asumir que el bloqueo es la única protección y retirar la cabecera para no aparentar una garantía que no existe.

La segunda es menor. En article-page.php, el 404 por artículo no publicado envía noindex, pero los otros dos casos de 404 (fecha futura y cuerpo vacío) responden 404 sin la cabecera. Un 404 ya sirve para que Google deje de indexar la URL, así que no es grave; lo dejo anotado porque si algún día cambiara el código de estado, la cabecera tampoco estaría en esos casos.

Un acierto del mismo archivo de robots.txt: en él hay un comentario que dice que /blog/feed.php no se bloquea porque participa en la carga del listado. Eso deja la URL rastreable y la cabecera noindex de feed.php sí se puede leer, que es el patrón correcto.

Cómo comprobar que funciona

La cabecera no se ve en el código fuente, así que hay que mirarla en la respuesta. Este es el orden que sigo:

Cuatro pasos de verificación numerados: curl -I, DevTools, Inspección de URL y revisión de la cabecera tras cada despliegue.
Primero lo que envía tu servidor, después lo que ve Google.
  1. curl -I. Muestra solo las cabeceras de la respuesta:
    curl -I https://tudominio.com/archivo.pdf
    Busca la línea x-robots-tag y comprueba que el código de estado es el esperado. Algunos servidores o aplicaciones responden distinto a una petición HEAD que a un GET; si dudas, curl -s -D - -o /dev/null URL hace un GET y muestra solo las cabeceras.
  2. DevTools. En la pestaña Network, selecciona la petición y revisa «Response Headers». Útil para páginas que cargan tras un redirect.
  3. Inspección de URL en Search Console. La documentación de Google indica que la herramienta permite ver lo que recibió Googlebot al rastrear la URL. Sirve para confirmar que la regla llegó, no para saber cuándo desaparecerá del índice.
  4. Tras cada despliegue. Una migración, un cambio de CDN o un nuevo bloque location pueden quitar o añadir la cabecera sin que nadie lo note. Compruébala después de tocar el servidor.

Dos comprobaciones cruzadas más: que la URL no esté en Disallow, y que no aparezca en el sitemap XML si le has puesto noindex, porque es una señal contradictoria.

Un noindex no saca la URL del índice en el momento. Google tiene que volver a rastrearla. Google no documenta un plazo y yo tampoco te lo voy a inventar: depende de la frecuencia de rastreo de esa URL.

Errores frecuentes

ErrorQué provocaCómo evitarlo
Disallow en robots.txt y noindex en cabecera a la vezGoogle no lee la cabecera; la URL puede seguir en resultados sin descripciónDejar la URL rastreable hasta que desaparezca
Regex sin escapar el punto ni anclar el finalLa regla afecta a más archivos de los previstosUsar \.pdf$ y probar con curl en URLs que no deberían encajar
add_header en Nginx sin alwaysLa cabecera no se envía en respuestas de errorAñadir always
add_header en un location que ya tenía otrosSe pierden las cabeceras del nivel superiorRepetirlas en el location o revisar la herencia
Regla heredada de stagingEl sitio en producción se queda en noindexRevisar cabeceras y meta robots en cada despliegue
header() tras salida de HTMLLa cabecera no se envía y PHP lanza un avisoEnviarla antes de cualquier salida
Fecha mal escrita en unavailable_afterLa regla se ignora sin avisoUsar un formato de los que cita Google, con zona horaria
Auditoría SEO

Ver auditoría SEO

Preguntas frecuentes

¿X-Robots-Tag sustituye a la meta robots?

No hace falta que la sustituya. Expresan las mismas instrucciones por dos vías. En páginas HTML que puedes editar, prefiero la meta robots por visibilidad. La cabecera es necesaria cuando no hay HTML, como en PDF o imágenes, o cuando quieres aplicar una regla por patrón desde el servidor.

¿Cómo pongo noindex a un PDF?

Enviando X-Robots-Tag: noindex en la respuesta de ese PDF, con un FilesMatch en Apache o un location en Nginx. El PDF debe poder rastrearse: no lo bloquees en robots.txt, o Google no verá la cabecera.

¿Puedo dirigir la regla solo a Googlebot?

Sí. Se antepone el user-agent: X-Robots-Tag: googlebot: noindex. Las reglas sin user-agent se aplican a todos los rastreadores, y las que llevan uno solo a ese.

¿Qué ocurre si la meta robots dice index y la cabecera dice noindex?

Se aplica la regla más restrictiva, así que la página no se indexa. La documentación de Google lo ilustra con max-snippet:50 y nosnippet, donde gana nosnippet.

¿Por qué no funciona mi noindex si lo tengo en la cabecera?

Las causas habituales son tres: la URL está bloqueada en robots.txt, la cabecera no llega porque otra capa (CDN, proxy) la elimina, o aún no se ha vuelto a rastrear. Empieza con curl -I y mira después la Inspección de URL.

¿Cuánto tarda Google en aplicar la cabecera?

Google no documenta un plazo. La regla se descubre cuando la URL se rastrea, así que depende de cuándo vuelva a pasar por ella. Para unavailable_after solo documenta que, tras la fecha, reduce considerablemente la frecuencia de rastreo.

¿Se puede combinar con data-nosnippet?

Son controles de ámbitos distintos. La cabecera, con nosnippet o max-snippet, afecta a toda la URL; data-nosnippet excluye solo un fragmento dentro de una página HTML. Si pones nosnippet en la cabecera, el atributo sobra en esa página.

Referencias y fuentes

Documentación consultada para este artículo.

  1. Robots Meta Tags Specifications Google Search Central
  2. Block Search indexing with noindex Google Search Central
  3. Introduction to robots.txt Google Search Central
  4. Apache Module mod_headers Apache HTTP Server
  5. Module ngx_http_headers_module nginx.org
  6. header() Manual de PHP
  7. X-Robots-Tag Sánchez Donate
  8. Robots Meta Tag y X-Robots-Tag: qué es y cómo usarlo Semrush

Sigue leyendo

Rastreo

· 13 min

robots.txt: qué controla, qué no y cómo configurarlo bien

Qué bloquea robots.txt y qué no, cómo se leen los grupos y comodines, qué hacer con los bots de IA y el robots.txt real de mi web, línea a línea.

Leer el artículo: robots.txt: qué controla, qué no y cómo configurarlo bien
Metaetiquetas

· 13 min

Etiqueta canonical SEO: qué hace y cómo implementarla bien

El canonical es una sugerencia, no una orden. Métodos, casos reales, errores típicos y cómo lo genero yo en mi propia web.

Leer el artículo: Etiqueta canonical SEO: qué hace y cómo implementarla bien

Tu próximo paso empieza con una conversación.

Cuéntame qué necesitas conseguir con tu web.

Hablemos de tu proyecto