Chunked Transfer es un mecanismo del protocolo HTTP mediante el cual el servidor transmite el cuerpo de la respuesta en fragmentos separados (chunks) sin especificar de antemano el tamaño total de los datos. Cada chunk contiene su tamaño en formato hexadecimal y datos de la longitud indicada, finalizando con un chunk de tamaño cero. Según MDN Web Docs, 2025, Transfer-Encoding: chunked se activa automáticamente cuando el tamaño de la respuesta se desconoce de antemano — por ejemplo, durante la generación de contenido sobre la marcha o la transmisión de datos en streaming.
Puntos Clave
Chunked Transfer es un mecanismo HTTP definido en la especificación HTTP/1.1 (RFC 7230, sección 4.1) que permite al servidor enviar el cuerpo de la respuesta en partes sin especificar el Content-Length total. En lugar de calcular el tamaño de la respuesta antes de enviarla, el servidor comienza la transmisión inmediatamente, enviando fragmentos de datos a medida que están disponibles. Cada fragmento va acompañado de su propio encabezado de tamaño, lo que permite al cliente ensamblar la respuesta a partir de piezas.
El mecanismo se activa mediante el encabezado Transfer-Encoding: chunked. Cuando el cliente ve este encabezado en la respuesta, sabe que el cuerpo se transmitirá en fragmentos y debe leer la respuesta en un bucle: leer el tamaño del fragmento, luego leer los datos del tamaño especificado, luego repetir. El proceso termina cuando se encuentra un fragmento de tamaño cero. Chunked Transfer es una parte obligatoria de HTTP/1.1, soportada por todos los servidores web modernos y clientes HTTP.
La principal razón para usar chunked transfer es la generación dinámica de contenido. Cuando el servidor genera una respuesta basada en una consulta a la base de datos, una API externa o un cálculo prolongado, no puede conocer el tamaño del resultado de antemano. En lugar de almacenar en búfer toda la respuesta en memoria (lo que es riesgoso para grandes volúmenes), el servidor activa Transfer-Encoding: chunked y envía datos a medida que están disponibles. Esto es especialmente importante para servidores con memoria limitada y para respuestas cuyo tamaño puede ser muy grande — desde 100 MB o más.
En HTTP/2, el mecanismo chunked transfer como tal no existe, ya que el protocolo utiliza multiplexación de flujos a nivel de tramas. En HTTP/2, los datos de cualquier tamaño se transmiten en tramas DATA, y no es necesario declarar el tamaño del cuerpo de la respuesta de antemano — un flujo puede cerrarse en cualquier momento. Los servidores modernos convierten automáticamente las respuestas chunked de HTTP/1.1 en transmisión por streaming equivalente al hacer proxy a un upstream HTTP/2. Chunked Transfer sigue siendo relevante para conexiones HTTP/1.1.
Cuando el servidor decide usar Chunked Transfer, no calcula Content-Length sino que envía el encabezado Transfer-Encoding: chunked. Luego, el cuerpo de la respuesta se forma como una secuencia de fragmentos. Cada fragmento comienza con una línea que contiene el tamaño del fragmento en formato hexadecimal (sin el prefijo 0x), seguida de CRLF ( ). Luego vienen los datos del fragmento del tamaño especificado, que terminan con CRLF. El último fragmento tiene tamaño 0, después del cual pueden seguir encabezados trailer.
El tamaño hexadecimal permite transmitir fragmentos de cualquier tamaño desde 1 byte hasta un volumen teóricamente ilimitado. En la práctica, el tamaño del fragmento lo elige el servidor: los valores típicos son 4 KB, 8 KB o 16 KB. El tamaño óptimo del fragmento debe ser múltiplo del tamaño del segmento TCP (generalmente 1460 bytes para Ethernet) para minimizar la fragmentación a nivel de transporte. Nginx usa fragmentos de 4 KB por defecto, Apache usa fragmentos de 8 KB.
Un cliente que recibe Transfer-Encoding: chunked debe leer la respuesta fragmento por fragmento hasta el fragmento cero de terminación. Si el cliente no soporta chunked transfer, el servidor no puede usar este modo. En la práctica, todos los clientes HTTP modernos — navegadores, OkHttp, URLSession, curl — soportan completamente las respuestas chunked. La lectura en streaming permite al cliente comenzar a procesar los datos antes de recibir la respuesta completa, lo cual es crítico para el rendimiento.
| Elemento del fragmento | Formato | Ejemplo |
|---|---|---|
| Tamaño del fragmento | HEX + CRLF | 1000 |
| Datos del fragmento | [tamaño bytes] + CRLF | [4096 bytes de datos] |
| Fragmento de terminación | 0 | 0 |
| Trailer (opcional) | Encabezados + CRLF | Expires: Wed, 21 Oct 2025 |
Chunked Transfer soporta encabezados trailer — encabezados HTTP adicionales que se transmiten después del último fragmento. Esto es útil para metadatos que se conocen solo después de completar la generación de la respuesta: por ejemplo, Content-MD5 o X-Compression-Ratio. Los encabezados trailer deben declararse en el encabezado Trailer: Trailer: Content-MD5, X-Compression-Ratio. En la práctica, los trailers rara vez se usan — la mayoría de los servidores no los incluyen en las respuestas.
Una respuesta chunked tiene una estructura estrictamente definida que el cliente debe analizar correctamente. Consideremos un ejemplo completo de una respuesta HTTP con Transfer-Encoding: chunked. Después de los encabezados y una línea vacía, comienza el cuerpo de la respuesta. La estructura del cuerpo es una secuencia de: tamaño_del_fragmento datos tamaño_del_fragmento datos ... hasta 0 . Cada tamaño se transmite en notación hexadecimal usando caracteres ASCII.
Ejemplo de respuesta del servidor con Chunked Transfer:
HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked
7
Hello
6
World!
0
En este ejemplo, el servidor transmite la cadena "Hello World!" en dos fragmentos. El primer fragmento tiene 7 bytes y contiene "Hello ", el segundo tiene 6 bytes y contiene "World!". El cliente recopila datos de ambos fragmentos y obtiene la cadena completa. Importante: el tamaño del fragmento incluye solo los datos, no los separadores CRLF de los propios fragmentos. El fragmento vacío de terminación (0 ) notifica al cliente que la transmisión ha finalizado.
import java.net.HttpURLConnection
import java.io.BufferedReader
import java.io.InputStreamReader
fun readChunkedResponse() {
val url = java.net.URL("https://stream.example.com/data")
val connection = url.openConnection() as HttpURLConnection
val reader = BufferedReader(
InputStreamReader(connection.inputStream)
)
var line: String?
while (reader.readLine().also { line = it } != null) {
println("Fragmento: $line")
}
reader.close()
}
OkHttp abstrae completamente al desarrollador de los detalles de Chunked Transfer. Al recibir una respuesta con Transfer-Encoding: chunked, OkHttp recopila automáticamente los fragmentos y proporciona al desarrollador el cuerpo completo de la respuesta a través de response.body?.string(). Para procesamiento en streaming, se usa response.body?.source(), que devuelve un BufferedSource y permite leer datos a medida que llegan. El desarrollador no necesita analizar manualmente los tamaños hex y CRLF — la biblioteca lo hace automáticamente.
Content-Length y Transfer-Encoding: chunked son dos formas mutuamente excluyentes de especificar el tamaño del cuerpo de un mensaje HTTP. Content-Length es un encabezado que contiene el tamaño exacto del cuerpo en bytes. Es obligatorio para respuestas cuyo tamaño se conoce de antemano y para solicitudes con cuerpo (POST, PUT). Content-Length permite al cliente asignar un búfer del tamaño requerido de antemano y verificar que se hayan recibido todos los datos.
Chunked Transfer se usa cuando el tamaño del cuerpo no se conoce de antemano. Esto ocurre en tres escenarios principales: generación dinámica de contenido (por ejemplo, una consulta a la base de datos cuyo resultado aún no está disponible), transmisión en streaming de archivos grandes (para evitar almacenar en búfer todo el archivo en memoria) y Server-Sent Events (SSE) para transmisión de eventos en tiempo real. La elección entre Content-Length y chunked es responsabilidad del servidor. Si el servidor conoce el tamaño antes de comenzar la transmisión, debe usar Content-Length como un mecanismo más simple y predecible.
La especificación HTTP/1.1 prohíbe el uso simultáneo de Content-Length y Transfer-Encoding: chunked. Si el servidor envía ambos encabezados, el cliente debe ignorar Content-Length y procesar la respuesta como chunked. La prioridad de Transfer-Encoding sobre Content-Length está establecida en RFC 7230 para casos en que un servidor proxy modifica el cuerpo de la respuesta y no puede preservar el Content-Length original. Algunos clientes HTTP antiguos manejan esta situación incorrectamente, pero las implementaciones modernas siguen la especificación.
Existen escenarios en los que Content-Length fundamentalmente no puede calcularse de antemano. Informes dinámicos generados bajo demanda con filtrado y agregación — el servidor no conoce el volumen de datos hasta que se completa la consulta a la base de datos. Video en streaming transmitido desde una cámara en tiempo real — el tamaño es infinito. SSE y long polling para notificaciones — la respuesta puede durar indefinidamente. En todos estos casos, Chunked Transfer es el único mecanismo correcto.
Chunked Transfer subyace a muchas tecnologías de streaming en la web. La más conocida es Server-Sent Events (SSE), donde el servidor envía eventos al cliente a través de una única conexión HTTP con Transfer-Encoding: chunked. SSE usa un formato de texto especial (data: mensaje ), pero la capa de transporte es chunked transfer ordinario. El navegador recibe los eventos a medida que el servidor los envía, sin esperar a que la respuesta se complete.
El streaming de audio y video también se basa en Chunked Transfer. Los servidores de medios como Nginx RTMP y Wowza Streaming Engine envían datos de medios en fragmentos a través de HTTP. El reproductor del lado del cliente comienza la reproducción tan pronto como se recibe el primer fragmento, sin esperar a que el archivo completo se cargue. Esto reduce el tiempo hasta el primer fotograma de decenas de segundos a 1-2 segundos. YouTube y Netflix usan exactamente este enfoque para sus flujos HTTP.
En el desarrollo móvil, Chunked Transfer se usa para transferir grandes volúmenes de datos sin cargar toda la respuesta en memoria. Al cargar imágenes a través de Coil o Glide en Android, las bibliotecas leen datos en streaming fragmento por fragmento y decodifican gradualmente la imagen. Esto permite mostrar imágenes grandes (10+ MB) sin OutOfMemoryError. OkHttp soporta lectura en streaming a través de response.body?.byteStream(), que devuelve un InputStream que lee datos fragmento por fragmento.
gRPC usa HTTP/2, donde el streaming está integrado a nivel de protocolo y no requiere un mecanismo chunked separado. Los servidores GraphQL que funcionan sobre HTTP/1.1 pueden usar Chunked Transfer para transmitir resultados de suscripciones en streaming. Apollo Server y Hasura envían respuestas chunked para suscripciones de GraphQL, transmitiendo eventos a medida que ocurren. El cliente recibe actualizaciones en tiempo real sin necesidad de polling.
Chunked Transfer proporciona ventajas importantes para las aplicaciones web. Envío inmediato de datos — el servidor no almacena en búfer la respuesta antes de enviarla, reduciendo la latencia hasta el primer byte. Procesamiento en streaming — el cliente puede comenzar a procesar los datos a medida que llegan sin esperar la descarga completa. Sin limitaciones de memoria — el servidor no almacena la respuesta completa en memoria, lo que es crítico para grandes volúmenes de datos. Capacidad de transmitir flujos infinitos — SSE, video en vivo, monitoreo.
Sin embargo, Chunked Transfer tiene limitaciones. Sobrecarga para cada fragmento es de 6 a 12 bytes para el tamaño + CRLF, lo que para muchos fragmentos pequeños (por ejemplo, 100 bytes cada uno) puede aumentar el tamaño de la respuesta en un 10-15%. Imposibilidad de especificar el tamaño exacto — el cliente no puede asignar un búfer de antemano ni mostrar una barra de progreso. Problemas con servidores proxy — algunos proxies antiguos no soportan chunked transfer y no pueden almacenar en caché dichas respuestas. Sin soporte para reanudar descargas — no se pueden hacer solicitudes Range para respuestas chunked recibidas parcialmente.
Según HTTP Archive, 2025, aproximadamente el 35% de todas las respuestas HTTP usan Transfer-Encoding: chunked. Entre ellas predominan las páginas dinámicas (60%), las respuestas de API (25%) y los flujos de medios (15%). Los archivos estáticos casi siempre usan Content-Length ya que su tamaño se conoce de antemano. La proporción de respuestas chunked está disminuyendo gradualmente con la adopción de HTTP/2, donde el streaming se implementa a nivel de trama sin necesidad de un encabezado Transfer-Encoding adicional.
En el desarrollo móvil, use Chunked Transfer para descargar archivos grandes (imágenes, video) y para solicitudes de API que devuelven grandes matrices de datos. OkHttp soporta completamente chunked transfer sin configuración adicional. Para cargas al servidor, Chunked Transfer no se usa — HTTP/1.1 no tiene Transfer-Encoding para cargas. En iOS, URLSession soporta tanto el envío como la recepción de datos chunked sin configuración especial. El análisis JSON en streaming (por ejemplo, a través de Jackson Streaming API o Moshi) permite procesar grandes matrices JSON a medida que llegan en un flujo chunked.
Preguntas Frecuentes
El servidor activa Chunked Transfer automáticamente cuando el tamaño de la respuesta es desconocido. Nginx añade Transfer-Encoding: chunked si no se establece Content-Length. En Spring Boot, StreamingResponseBody y SseEmitter usan automáticamente chunked transfer. En Node.js Express, la respuesta se vuelve chunked si se llama a res.write() y res.end() sin Content-Length.
No, la especificación HTTP/1.1 prohíbe el uso simultáneo de Content-Length y Transfer-Encoding: chunked. Si el servidor envía ambos encabezados, el cliente debe ignorar Content-Length y procesar la respuesta como chunked. Esta regla está establecida en RFC 7230 para compatibilidad con servidores proxy que pueden modificar el cuerpo de la respuesta.
El tamaño óptimo del fragmento depende del escenario. Para páginas web ordinarias — 4-8 KB. Para transmisión de video — 16-64 KB. Para SSE — fragmentos mínimos de 1-2 KB para reducir la latencia. El tamaño del fragmento debe ser múltiplo del tamaño del segmento TCP (1460 bytes para Ethernet) para minimizar la fragmentación a nivel de transporte.
Los servidores proxy modernos (Nginx, HAProxy, Envoy) soportan Chunked Transfer. El proxy puede reenviar fragmentos sin almacenamiento en búfer (streaming) o almacenar en búfer toda la respuesta y reenviarla con Content-Length. Los proxies antiguos pueden almacenar en búfer la respuesta chunked hasta que se complete, aumentando la latencia. HTTP/2 resuelve este problema a nivel de protocolo.
Son lo mismo. Chunked Transfer es el nombre completo del mecanismo de la especificación HTTP/1.1. HTTP chunked encoding es lo mismo, a veces usado en la documentación de bibliotecas. Transfer-Encoding: chunked es el encabezado que activa este modo. Los tres términos describen el mismo mecanismo de transmisión de datos en partes.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también