HTTPQUERY
Español

304 Not Modified

Uso

El código de estado 304 Not Modified se envía cuando la solicitud es segura, como una solicitud GET o HEAD, y el servidor determina que el recurso no ha cambiado respecto a la versión almacenada en la caché del cliente. Esto ahorra ancho de banda, ya que el servidor no retransmite datos que el cliente ya posee.

Nota

304 Not Modified no es una redirección, pese a pertenecer a la clase de estados 3xx. Las redirecciones (301, 302, 307, 308) envían al cliente a una URL distinta mediante la cabecera Location. El 304 indica al cliente que reutilice su copia en caché del mismo recurso, y no se envía ninguna cabecera Location. Las herramientas de desarrollo del navegador a veces agrupan el 304 con las redirecciones, lo que aumenta la confusión.

Nota

“200 (from disk cache)” en las herramientas de desarrollo significa que el navegador sirvió el recurso desde la caché sin contactar con el servidor, porque el max-age de Cache-Control aún no ha expirado. El 304 significa que el navegador contactó con el servidor para revalidar y el servidor confirmó que la copia en caché está vigente. Un 200 servido desde caché no implica ninguna petición de red, mientras que un 304 implica una ida y vuelta.

El servidor genera una o varias de las siguientes cabeceras en la respuesta:

Dado que el objetivo de la respuesta 304 Not Modified es minimizar el ancho de banda, el servidor omite las cabeceras que no estaban incluidas en la solicitud original, salvo que ayuden al proceso de actualización de la caché.

En las solicitudes GET condicionales, las directivas relevantes son If-None-Match e If-Modified-Since. Ambas se apoyan en un validador como ETag para evaluar si el recurso necesita retransmitirse.

Ejemplo

El cliente solicita un recurso, recibe un ETag que identifica la versión y más tarde revalida. El servidor reconoce que el recurso no ha cambiado y devuelve 304 Not Modified. En la tercera solicitud hay disponible una versión nueva y se envía una respuesta 200 completa con un ETag actualizado.

Nota

Cada vez que el servidor actualiza un recurso, se genera un ETag nuevo. Como alternativa, el servidor devuelve una fecha Last-Modified y el cliente usa If-Modified-Since en su lugar, lo que evita que el servidor tenga que mantener un historial de ETag.

Impacto en SEO

Cuando Googlebot recibe un 304, el rastreador reconoce que el contenido no ha cambiado desde el último rastreo. La canalización de indexación recalcula las señales de clasificación de la URL, pero no vuelve a descargar ni a indexar el contenido.

Trampa del 304 obsoleto

Un 304 confirma que la versión en caché sigue vigente. Si el servidor sirvió previamente una página rota (cuerpo vacío, contenido de error) con un 200 y el rastreador almacenó ese resultado, un 304 posterior le indica al rastreador que la versión rota persiste. El rastreador deja de volver a comprobarla porque el “contenido” no ha cambiado. Arreglar la página por sí solo no basta. El servidor debe devolver un 200 nuevo con el cuerpo corregido (y un ETag nuevo) para sustituir el error almacenado en caché. Depurar este escenario es difícil porque la causa raíz (un error transitorio del pasado) ya no es visible.

Solicitud inicial

GET /news.html HTTP/1.1
Host: example.com

Respuesta inicial

HTTP/1.1 200 OK
ETag: "1234000"
Content-Type: text/html
Content-Length: 1250

<message body contains requested resource>

Segunda solicitud

GET /news.html HTTP/1.1
Host: example.com
If-None-Match: "1234000"

Segunda respuesta

HTTP/1.1 304 Not Modified
ETag: "1234000"

Tercera solicitud

GET /news.html HTTP/1.1
Host: example.com
If-None-Match: "1234000"

Tercera respuesta

HTTP/1.1 200 OK
ETag: "1234001"
Content-Type: text/html
Content-Length: 1600

<message body contains requested resource>

Referencias de código

.NET

HttpStatusCode.NotModified

Rust

http::StatusCode::NOT_MODIFIED

Rails

:not_modified

Go

http.StatusNotModified

Symfony

Response::HTTP_NOT_MODIFIED

Python3.5+

http.HTTPStatus.NOT_MODIFIED

Java

java.net.HttpURLConnection.HTTP_NOT_MODIFIED

Apache HttpComponents Core

org.apache.hc.core5.http.HttpStatus.SC_NOT_MODIFIED

Angular

@angular/common/http/HttpStatusCode.NotModified