Saltar al contenido

.htaccess y caché: activar gzip y Brotli, la caché del navegador y bloquear bots de IA en Apache

Publicado el 07-10-20268 min de lecturaPor la redacción de SmoothSeen

En el .htaccess de Apache, la compresión se activa con AddOutputFilterByType para Brotli y gzip, solo en tipos de texto. La caché del navegador se fija con mod_expires por tipo de fichero y con un Cache-Control de un año e immutable solo para ficheros con huella en el nombre. Los bots de IA de entrenamiento se vetan con mod_rewrite y un 403, sin tocar a los de búsqueda.

Lo esencial

  • Con mod_brotli y mod_deflate, un HTML de 6.143 bytes viajó en 301 bytes con Brotli y en 414 con gzip en nuestra prueba con Apache httpd 2.4.69.
  • Las imágenes WebP, JPEG o AVIF ya van comprimidas; meterlas en la lista de compresión gasta CPU sin ahorrar bytes.
  • Un año de caché con immutable solo es seguro para ficheros con huella en el nombre; el HTML debe llevar no-cache para que se revalide en cada visita.
  • Vetar GPTBot, ClaudeBot o CCBot es una decisión editorial que no te saca de ChatGPT ni de Claude; vetar OAI-SearchBot, Claude-SearchBot o PerplexityBot, sí.
  • Un veto por user-agent no para a quien lo falsifica, y Google-Extended y Applebot-Extended solo se controlan en robots.txt.

Para comprobarlo en tu web: Auditoría SEO

En esta página

Apache decide tres cosas de esta guía: si un fichero viaja comprimido, cuánto tiempo puede guardarlo el navegador y a quién responde con un 403. No decide lo que haga un CDN que tengas delante, ni puede distinguir a un bot que se hace pasar por otro. Los fragmentos se han probado el 07-10-2026 con Apache httpd 2.4.69 en su imagen oficial de Docker (httpd:2.4), con curl desde otro contenedor. La redirección a HTTPS y las cabeceras de seguridad están en la guía de .htaccess para HTTPS, HSTS y cabeceras.

¿Qué módulos necesitas y cómo sabes si están?

Módulo
mod_deflate
Para qué
Compresión gzip
Nota
Envía Vary: Accept-Encoding por su cuenta1
Módulo
mod_brotli
Para qué
Compresión Brotli
Nota
Disponible desde Apache 2.4.262
Módulo
mod_filter
Para qué
La directiva AddOutputFilterByType
Nota
Cargado en el httpd.conf de serie
Módulo
mod_expires
Para qué
Expires y el max-age de Cache-Control por tipo
Nota
Se puede usar en .htaccess3
Módulo
mod_headers
Para qué
Cualquier otra cabecera, como immutable
Nota
Módulo
mod_rewrite
Para qué
El veto por user-agent
Nota

La imagen oficial trae los seis compilados, pero el httpd.conf de serie deja comentados mod_deflate, mod_brotli, mod_expires y mod_rewrite. En un hosting compartido no puedes verlo directamente: pregunta a soporte o haz la prueba del final. Si el módulo no está cargado, la directiva da un error 500, y eso es bueno: te enteras. Por eso este .htaccess no usa <IfModule>, que escondería el fallo.

Un recordatorio de la documentación de Apache: si tienes acceso a la configuración principal, pon esto en el VirtualHost, porque el .htaccess se lee en cada petición4.

Paso 1: compresión Brotli y gzip

AddOutputFilterByType BROTLI_COMPRESS text/html text/plain text/css text/javascript application/javascript application/json application/xml image/svg+xml
AddOutputFilterByType DEFLATE text/html text/plain text/css text/javascript application/javascript application/json application/xml image/svg+xml

En la prueba, Apache respondió con Brotli cuando la petición aceptaba br y gzip, con gzip cuando solo aceptaba gzip, y sin comprimir cuando no pedía compresión. Estos son los bytes transferidos:

Fichero
HTML (index.html)
Sin comprimir
6.143
gzip
414
Brotli
301
Fichero
CSS
Sin comprimir
4.710
gzip
286
Brotli
156
Fichero
JavaScript
Sin comprimir
5.670
gzip
302
Brotli
192
Fichero
Imagen WebP
Sin comprimir
4.000
gzip
4.000
Brotli
4.000

Los ficheros de prueba son muy repetitivos y comprimen más que una web real; lo que importa es el orden de magnitud y que Brotli quedó por debajo de gzip en los tres textos.

Tres detalles que conviene saber:

  • text/javascript y application/javascript, los dos. El mime.types de Apache 2.4.69 sirve los .js como text/javascript; muchos ejemplos antiguos solo listan application/javascript y el JavaScript sale sin comprimir.
  • Las imágenes, fuera. WebP, JPEG, PNG y AVIF ya van comprimidos. La documentación de mod_deflate las excluye en sus ejemplos1. SVG sí es texto y sí se comprime.
  • BREACH. Las documentaciones de los dos módulos avisan de que algunas aplicaciones web son vulnerables a una fuga de información cuando una conexión TLS transporta datos comprimidos, y remiten a la familia de ataques BREACH12. Si tu web maneja tokens o datos personales en páginas dinámicas, revísalo antes de activarla en ellas.

Paso 2: caché del navegador sin servir versiones viejas

La regla de web.dev es sencilla: las URL con versión o huella en el nombre pueden guardarse un año (max-age=31536000), y las URL sin versión, como el HTML, deben llevar no-cache, que no significa «no guardes» sino «revalida antes de usar»5. MDN añade que immutable indica que la respuesta no cambiará mientras esté fresca, pensado justo para ese patrón de ficheros con huella6.

ExpiresActive On
ExpiresByType text/css "access plus 1 week"
ExpiresByType text/javascript "access plus 1 week"
ExpiresByType image/webp "access plus 1 month"
ExpiresByType image/avif "access plus 1 month"
ExpiresByType image/png "access plus 1 month"
ExpiresByType image/jpeg "access plus 1 month"
ExpiresByType font/woff2 "access plus 1 year"

# El HTML se guarda, pero se revalida en cada visita
Header set Cache-Control "no-cache" "expr=%{CONTENT_TYPE} =~ m#^text/html#"

# Ficheros con huella en el nombre (app.3f9a1c2b.js): un año e immutable
<FilesMatch "\.[0-9a-f]{8,}\.(css|js|mjs|woff2|webp|avif|png|jpe?g|svg)$">
    Header set Cache-Control "max-age=31536000, immutable"
</FilesMatch>

Las cabeceras que devolvió Apache 2.4.69:

Petición
/ (HTML)
Cache-Control obtenido
no-cache
Petición
/assets/estilos.css
Cache-Control obtenido
max-age=604800
Petición
/assets/app.3f9a1c2b.js
Cache-Control obtenido
max-age=31536000, immutable
Petición
/assets/foto.webp
Cache-Control obtenido
max-age=2592000

Dos decisiones de este bloque:

  1. El HTML se reconoce por su tipo, no por la extensión. La condición expr= sobre el tipo de contenido cubre cualquier respuesta HTML, termine o no su fichero en .html. Si tu CMS ya envía su propio Cache-Control, comprueba con curl cuál sale al final.
  2. El JavaScript con huella también recibe un Expires de una semana de mod_expires. No pasa nada: cuando una respuesta trae max-age, la norma HTTP obliga a ignorar Expires7.

El error que más cuesta ver: poner immutable a estilos.css sin huella. Si mañana cambias ese fichero, quien ya lo tenga en caché seguirá con la versión vieja hasta un año. Si tu CMS no añade huellas a los nombres, quédate con una semana.

Paso 3: bots de IA, separando búsqueda y entrenamiento

No todos los bots de IA hacen lo mismo, y vetar al equivocado tiene consecuencias distintas:

Bot
OAI-SearchBot
Empresa
OpenAI
Para qué lo usa su dueño
Mostrar webs en la búsqueda de ChatGPT
Si lo vetas
No apareces en las respuestas de búsqueda de ChatGPT8
Bot
GPTBot
Empresa
OpenAI
Para qué lo usa su dueño
Entrenar modelos
Si lo vetas
Tu contenido no se usa para entrenar; sigues pudiendo salir en ChatGPT8
Bot
Claude-SearchBot y Claude-User
Empresa
Anthropic
Para qué lo usa su dueño
Búsqueda y consultas de usuarios de Claude
Si lo vetas
Puede reducir tu visibilidad en Claude9
Bot
ClaudeBot
Empresa
Anthropic
Para qué lo usa su dueño
Entrenar modelos
Si lo vetas
Se excluye tu contenido futuro del entrenamiento9
Bot
PerplexityBot
Empresa
Perplexity
Para qué lo usa su dueño
Enlazar webs en sus resultados; no entrena modelos
Si lo vetas
Tus páginas pueden dejar de aparecer enlazadas en sus resultados10
Bot
CCBot
Empresa
Common Crawl
Para qué lo usa su dueño
Archivo abierto de la web
Si lo vetas
Sales de ese archivo11

El veto que probamos deja fuera a tres rastreadores de entrenamiento (GPTBot, ClaudeBot, meta-externalagent) y al de Common Crawl, y deja siempre abierto robots.txt:

RewriteEngine On
RewriteCond %{REQUEST_URI} !^/robots\.txt$
RewriteCond %{HTTP_USER_AGENT} (GPTBot|ClaudeBot|CCBot|meta-externalagent) [NC]
RewriteRule ^ - [F]

Con user-agent como los que envían estos bots, los cuatro vetados recibieron 403 en /blog/ y 200 en /robots.txt. OAI-SearchBot, ChatGPT-User, Claude-SearchBot, PerplexityBot, Googlebot y un Chrome normal recibieron 200 en las dos. La excepción de robots.txt no es un adorno: Anthropic explica que bloquear a sus bots por IP les impide leer tu robots.txt y que eso puede no garantizar la exclusión9.

Antes de usarlo, cuatro límites:

  • El user-agent se puede falsificar. Common Crawl dice que conoce rastreadores que se hacen pasar por CCBot y recomienda comprobar los rangos de IP que publica11. OpenAI y Perplexity también publican los suyos810.
  • Google-Extended y Applebot-Extended no son user-agents. Google-Extended es solo una marca de robots.txt, no afecta a la Búsqueda de Google y no tiene user-agent propio12. Applebot-Extended no rastrea páginas13. Una regla en el .htaccess no los ve: se controlan en robots.txt.
  • ChatGPT-User y Perplexity-User pueden no seguir robots.txt, según sus dueños, porque actúan cuando un usuario lo pide810. Si los vetas en el servidor, desapareces de esas consultas.
  • Un 403 no se ve en robots.txt. Si otro miembro del equipo revisa solo robots.txt, no sabrá que existe el veto. Documéntalo.

Para los bots que respetan robots.txt, robots.txt es la vía más limpia: está documentada por cada empresa y cualquiera puede leerla. El veto del .htaccess queda como refuerzo:

User-agent: GPTBot
User-agent: ClaudeBot
User-agent: CCBot
User-agent: meta-externalagent
User-agent: Google-Extended
User-agent: Applebot-Extended
Disallow: /

User-agent: *
Allow: /

Cómo comprobarlo

  1. Compresión. curl -sI -H "Accept-Encoding: br, gzip" https://www.example.com/ tiene que mostrar Content-Encoding: br; con "Accept-Encoding: gzip", Content-Encoding: gzip. En el panel Red de las herramientas del navegador también lo ves.
  2. Caché. curl -sI sobre la portada, un CSS y un fichero con huella: compara cada Cache-Control con la tabla del paso 2.
  3. Bots. curl -sI -A "GPTBot/1.4" https://www.example.com/ debe dar 403; curl -sI -A "OAI-SearchBot/1.4" https://www.example.com/, 200; y /robots.txt con el user-agent vetado, 200.
  4. Después de cada cambio, pide una página. httpd -t no lee los .htaccess: un error solo aparece como 500 al pedir la página.

Qué hace SmoothSeen con esto

SmoothSeen comprueba si tu web sirve el texto comprimido con gzip o Brotli dentro de Posicionamiento web. En Posicionamiento IA lee tu robots.txt separando los rastreadores de búsqueda de los de entrenamiento, sin contar como fallo vetar a los de entrenamiento, y pide la página con el user-agent de cada rastreador de IA, de un navegador y de Googlebot para detectar si el servidor o el cortafuegos responde 403 a alguno.

Qué hacer esta semana

Pide tu portada con curl -sI -H "Accept-Encoding: br, gzip" y con -A "OAI-SearchBot/1.4". Si no sale comprimida, o si el rastreador de búsqueda de ChatGPT recibe un 403 que nadie decidió, empieza por ahí. Para comprobar a la vez la compresión, robots.txt y los vetos del servidor, analiza tu web con SmoothSeen.

Preguntas frecuentes

¿Brotli o gzip: cuál activo?

Los dos. El navegador anuncia en cada petición qué algoritmos acepta; con los dos filtros activos, en nuestra prueba Apache usó Brotli cuando se aceptaba y gzip cuando no. Así, Brotli sirve a los navegadores modernos y gzip queda para los demás. Brotli dejó el HTML en 301 bytes frente a 414 con gzip. Si tu hosting no tiene mod_brotli, gzip solo ya es una mejora grande.

¿Por qué mis cambios de CSS no se ven después de activar la caché?

Porque el navegador sigue usando la copia guardada mientras no caduque. Es lo que pasa si das una caché larga, o immutable, a un fichero cuyo nombre no cambia cuando cambia su contenido. La solución es añadir una huella o un número de versión al nombre en cada publicación, o bajar la duración de esos ficheros a una semana.

¿Bloquear GPTBot me saca de ChatGPT?

No. OpenAI explica que GPTBot se usa para entrenar modelos y que la búsqueda de ChatGPT depende de OAI-SearchBot, con ajustes independientes para cada uno. Puedes vetar el entrenamiento y seguir saliendo en las respuestas con búsqueda. Lo que sí te saca es vetar a OAI-SearchBot, en robots.txt o con un 403 en el servidor.

¿Es mejor bloquear bots en robots.txt o en .htaccess?

Para los que respetan robots.txt, robots.txt: es la vía que documentan sus dueños, se ve desde fuera y no rompe nada si te equivocas de nombre. El .htaccess sirve para reforzarlo o para bots que no lo respetan, pero solo frena a quien se identifica con honradez y es invisible para quien revise robots.txt.

Fuentes

  1. 1Apache Module mod_deflate, Apache Software Foundation, consultada el 07-10-2026.
  2. 2Apache Module mod_brotli, Apache Software Foundation, consultada el 07-10-2026.
  3. 3Apache Module mod_expires, Apache Software Foundation, consultada el 07-10-2026.
  4. 4Apache HTTP Server Tutorial: .htaccess files, Apache Software Foundation, consultada el 07-10-2026.
  5. 5Prevent unnecessary network requests with the HTTP Cache, web.dev (Google), consultada el 07-10-2026.
  6. 6Cache-Control, MDN Web Docs, actualizada el 17-09-2026.
  7. 7RFC 9111: HTTP Caching, sección 5.3 (Expires), IETF, junio de 2022.
  8. 8Overview of OpenAI Crawlers, OpenAI, consultada el 07-10-2026.
  9. 9Does Anthropic crawl data from the web, and how can site owners block the crawler?, Anthropic, actualizada el 07-04-2026.
  10. 10Perplexity Crawlers, Perplexity, consultada el 07-10-2026.
  11. 11CCBot, Common Crawl, consultada el 07-10-2026.
  12. 12Google's common crawlers: Google-Extended, Google Search Central, actualizada el 14-07-2026.
  13. 13About Applebot, Apple, publicada el 04-09-2026.

Cómo citar este artículo

SmoothSeen. (2026, 7 de octubre). .htaccess y caché: activar gzip y Brotli, la caché del navegador y bloquear bots de IA en Apache. https://smoothseen.com/es/blog/apache-htaccess-compresion-cache-bots/

Quién lo escribe

SmoothSeen es una herramienta de auditoría web que mide el posicionamiento en buscadores y en asistentes de IA y entrega informes con la marca de la agencia.

Este blog es de SmoothSeen: cuando un artículo habla del producto, lo hace sabiendo que es el nuestro. Las cifras de terceros enlazan a su fuente original.

Historial de cambios

  • Primera versión.

Sigue leyendo

.htaccess: caché, gzip, Brotli y bloqueo de bots de IA