Chunked Transfer no desenvolvimento web — o que é, formato e princípio da transferência por chunks

Autor: IT Sectr Publicado: 2026-03-10 Tempo de leitura: 9 min

Chunked Transfer é um mecanismo do protocolo HTTP no qual o servidor transmite o corpo da resposta em fragmentos separados (chunks) sem especificar o tamanho total dos dados antecipadamente. Cada chunk contém seu tamanho em formato hexadecimal e dados do comprimento especificado, terminando com um chunk final de tamanho zero. De acordo com MDN Web Docs, 2025, Transfer-Encoding: chunked é ativado automaticamente pelo servidor quando o tamanho da resposta é desconhecido antecipadamente — por exemplo, durante a geração de conteúdo em tempo real ou transmissão de dados em streaming.

Pontos Principais

  • Chunked Transfer — transmissão de resposta HTTP em partes sem especificação prévia de Content-Length.
  • Transfer-Encoding: chunked — o cabeçalho que ativa o modo de transferência de dados por chunks.
  • Cada chunk contém seu tamanho em hex, dados e um CRLF final, e o fim é indicado por um chunk de tamanho zero.
  • Streaming — o uso principal de chunked transfer para transmissão de áudio, vídeo e eventos SSE.
  • Chunked Transfer é incompatível com o cabeçalho Content-Length — não são usados simultaneamente.

O que é Chunked Transfer?

Chunked Transfer é um mecanismo HTTP definido na especificação HTTP/1.1 (RFC 7230, seção 4.1) que permite ao servidor enviar o corpo da resposta em partes sem especificar o Content-Length total. Em vez de calcular o tamanho da resposta antes de enviar, o servidor começa a transmissão imediatamente, enviando fragmentos de dados à medida que ficam prontos. Cada fragmento é acompanhado por seu próprio cabeçalho de tamanho, permitindo que o cliente monte a resposta a partir das peças.

O mecanismo é ativado pelo cabeçalho Transfer-Encoding: chunked. Quando o cliente vê este cabeçalho na resposta, ele sabe que o corpo será transmitido em chunks e deve ler a resposta em um loop: ler o tamanho do chunk, depois ler os dados do tamanho especificado, depois repetir. O processo termina quando um chunk de tamanho zero é encontrado. Chunked Transfer é uma parte obrigatória do HTTP/1.1, suportada por todos os servidores web modernos e clientes HTTP.

A principal razão para usar chunked transfer é a geração dinâmica de conteúdo. Quando o servidor gera uma resposta baseada em uma consulta de banco de dados, API externa ou cálculo longo, ele não pode saber o tamanho do resultado antecipadamente. Em vez de armazenar em buffer a resposta inteira na memória (o que é arriscado para grandes volumes), o servidor ativa Transfer-Encoding: chunked e envia dados à medida que ficam disponíveis. Isso é especialmente importante para servidores com memória limitada e para respostas cujo tamanho pode ser muito grande — a partir de 100 MB ou mais.

Diferença entre HTTP/1.1 chunked e HTTP/2

Em HTTP/2, o mecanismo chunked transfer como tal não existe, pois o protocolo usa multiplexação de fluxos no nível de quadros. Em HTTP/2, dados de qualquer tamanho são transmitidos em quadros DATA, e o tamanho do corpo da resposta não precisa ser declarado antecipadamente — um fluxo pode ser fechado a qualquer momento. Servidores modernos convertem automaticamente respostas chunked HTTP/1.1 em transmissão por streaming equivalente ao fazer proxy para um upstream HTTP/2. Chunked Transfer permanece relevante para conexões HTTP/1.1.

Como funciona a transferência por chunks

Quando o servidor decide usar Chunked Transfer, ele não calcula Content-Length, mas envia o cabeçalho Transfer-Encoding: chunked. Em seguida, o corpo da resposta é formado como uma sequência de chunks. Cada chunk começa com uma linha contendo o tamanho do chunk em formato hexadecimal (sem o prefixo 0x), seguido por CRLF ( ). Em seguida, vêm os dados do chunk do tamanho especificado, terminando com CRLF. O último chunk tem tamanho 0, após o qual cabeçalhos trailer podem seguir.

O tamanho hexadecimal permite transmitir chunks de qualquer tamanho, de 1 byte a um volume teoricamente ilimitado. Na prática, o tamanho do chunk é escolhido pelo servidor: valores típicos são 4 KB, 8 KB ou 16 KB. O tamanho ideal do chunk deve ser múltiplo do tamanho do segmento TCP (geralmente 1460 bytes para Ethernet) para minimizar a fragmentação no nível de transporte. Nginx usa chunks de 4 KB por padrão, Apache usa chunks de 8 KB.

Um cliente que recebe Transfer-Encoding: chunked deve ler a resposta chunk por chunk até o chunk zero de terminação. Se o cliente não suporta chunked transfer, o servidor não pode usar este modo. Na prática, todos os clientes HTTP modernos — navegadores, OkHttp, URLSession, curl — suportam completamente respostas chunked. A leitura em streaming permite que o cliente comece a processar dados antes de receber a resposta completa, o que é crítico para o desempenho.

Elemento do chunkFormatoExemplo
Tamanho do chunkHEX + CRLF1000
Dados do chunk[tamanho bytes] + CRLF[4096 bytes de dados]
Chunk de terminação0 0
Trailer (opcional)Cabeçalhos + CRLFExpires: Wed, 21 Oct 2025

Cabeçalhos Trailer em Chunked Transfer

Chunked Transfer suporta cabeçalhos trailer — cabeçalhos HTTP adicionais que são transmitidos após o último chunk. Isso é útil para metadados que se tornam conhecidos somente após a conclusão da geração da resposta: por exemplo, Content-MD5 ou X-Compression-Ratio. Cabeçalhos trailer devem ser declarados no cabeçalho Trailer: Trailer: Content-MD5, X-Compression-Ratio. Na prática, trailers raramente são usados — a maioria dos servidores não os inclui nas respostas.

Formato de resposta chunked

Uma resposta chunked tem uma estrutura estritamente definida que o cliente deve analisar corretamente. Vamos considerar um exemplo completo de uma resposta HTTP com Transfer-Encoding: chunked. Após os cabeçalhos e uma linha vazia, o corpo da resposta começa. A estrutura do corpo é uma sequência de: tamanho_do_chunk dados tamanho_do_chunk dados ... até 0 . Cada tamanho é transmitido em notação hexadecimal usando caracteres ASCII.

Exemplo de resposta do servidor com Chunked Transfer:
HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked

7
Hello
6
World!
0

Neste exemplo, o servidor transmite a string "Hello World!" em dois chunks. O primeiro chunk tem 7 bytes contendo "Hello ", o segundo tem 6 bytes contendo "World!". O cliente coleta dados de ambos os chunks e obtém a string completa. Importante: o tamanho do chunk inclui apenas os dados, não os separadores CRLF dos próprios chunks. O chunk vazio de terminação (0 ) notifica o cliente que a transmissão foi concluída.

kotlin
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("Chunk: $line")
    }
    reader.close()
}

Analisar resposta chunked no OkHttp

OkHttp abstrai completamente o desenvolvedor dos detalhes do Chunked Transfer. Ao receber uma resposta com Transfer-Encoding: chunked, OkHttp coleta automaticamente os chunks e fornece ao desenvolvedor o corpo completo da resposta através de response.body?.string(). Para processamento em streaming, usa-se response.body?.source(), que retorna um BufferedSource e permite ler dados à medida que chegam. O desenvolvedor não precisa analisar manualmente tamanhos hex e CRLF — a biblioteca faz isso automaticamente.

Chunked Transfer vs Content-Length

Content-Length e Transfer-Encoding: chunked são duas formas mutuamente exclusivas de especificar o tamanho do corpo de uma mensagem HTTP. Content-Length é um cabeçalho que contém o tamanho exato do corpo em bytes. É obrigatório para respostas cujo tamanho é conhecido antecipadamente e para requisições com corpo (POST, PUT). Content-Length permite que o cliente aloque um buffer do tamanho necessário antecipadamente e verifique se todos os dados foram recebidos.

Chunked Transfer é usado quando o tamanho do corpo não é conhecido antecipadamente. Isso ocorre em três cenários principais: geração dinâmica de conteúdo (por exemplo, uma consulta ao banco de dados cujo resultado ainda não está disponível), transmissão em streaming de arquivos grandes (para evitar armazenar o arquivo inteiro em buffer na memória) e Server-Sent Events (SSE) para transmissão de eventos em tempo real. A escolha entre Content-Length e chunked é responsabilidade do servidor. Se o servidor conhece o tamanho antes do início da transmissão, ele deve usar Content-Length como um mecanismo mais simples e previsível.

A especificação HTTP/1.1 proíbe o uso simultâneo de Content-Length e Transfer-Encoding: chunked. Se o servidor enviar ambos os cabeçalhos, o cliente deve ignorar Content-Length e processar a resposta como chunked. A prioridade de Transfer-Encoding sobre Content-Length é estabelecida na RFC 7230 para casos em que um servidor proxy modifica o corpo da resposta e não pode preservar o Content-Length original. Alguns clientes HTTP antigos lidam com esta situação incorretamente, mas implementações modernas seguem a especificação.

Quando Content-Length é impossível

Existem cenários em que Content-Length fundamentalmente não pode ser calculado antecipadamente. Relatórios dinâmicos gerados sob demanda com filtragem e agregação — o servidor não conhece o volume de dados até que a consulta ao banco de dados seja concluída. Vídeo em streaming transmitido de uma câmera em tempo real — o tamanho é infinito. SSE e long polling para notificações — a resposta pode durar indefinidamente. Em todos estes casos, Chunked Transfer é o único mecanismo correto.

Streaming baseado em chunked transfer

Chunked Transfer está na base de muitas tecnologias de streaming na web. A mais conhecida é Server-Sent Events (SSE), onde o servidor envia eventos ao cliente através de uma única conexão HTTP com Transfer-Encoding: chunked. SSE usa um formato de texto especial (data: mensagem ), mas a camada de transporte é chunked transfer comum. O navegador recebe os eventos à medida que o servidor os envia, sem esperar a resposta ser concluída.

O streaming de áudio e vídeo também depende de Chunked Transfer. Servidores de mídia como Nginx RTMP e Wowza Streaming Engine enviam dados de mídia em chunks via HTTP. O player do lado do cliente inicia a reprodução assim que o primeiro chunk é recebido, sem esperar o arquivo completo carregar. Isso reduz o tempo até o primeiro quadro de dezenas de segundos para 1-2 segundos. YouTube e Netflix usam exatamente esta abordagem para seus fluxos HTTP.

No desenvolvimento móvel, Chunked Transfer é usado para transferir grandes volumes de dados sem carregar a resposta inteira na memória. Ao carregar imagens via Coil ou Glide no Android, as bibliotecas leem dados de streaming chunk por chunk e decodificam gradualmente a imagem. Isso permite exibir imagens grandes (10+ MB) sem OutOfMemoryError. OkHttp suporta leitura em streaming via response.body?.byteStream(), que retorna um InputStream que lê dados chunk por chunk.

Chunked transfer em gRPC e GraphQL

gRPC usa HTTP/2, onde o streaming é incorporado no nível do protocolo e não requer um mecanismo chunked separado. Servidores GraphQL rodando sobre HTTP/1.1 podem usar Chunked Transfer para transmitir resultados de assinaturas em streaming. Apollo Server e Hasura enviam respostas chunked para assinaturas GraphQL, transmitindo eventos à medida que ocorrem. O cliente recebe atualizações em tempo real sem necessidade de polling.

Vantagens e limitações

Chunked Transfer fornece vantagens importantes para aplicações web. Envio imediato de dados — o servidor não armazena a resposta em buffer antes de enviar, reduzindo a latência até o primeiro byte. Processamento em streaming — o cliente pode começar a processar dados à medida que chegam sem esperar o download completo. Sem limitações de memória — o servidor não armazena a resposta completa na memória, o que é crítico para grandes volumes de dados. Capacidade de transmitir fluxos infinitos — SSE, vídeo ao vivo, monitoramento.

No entanto, Chunked Transfer tem limitações. Sobrecarga para cada chunk é de 6 a 12 bytes para tamanho + CRLF, o que para muitos chunks pequenos (por exemplo, 100 bytes cada) pode aumentar o tamanho da resposta em 10-15%. Incapacidade de especificar o tamanho exato — o cliente não pode alocar um buffer antecipadamente ou mostrar uma barra de progresso. Problemas com servidores proxy — alguns proxies antigos não suportam chunked transfer e não podem armazenar em cache tais respostas. Sem suporte para retomar downloads — requisições Range não podem ser feitas para respostas chunked recebidas parcialmente.

De acordo com HTTP Archive, 2025, cerca de 35% de todas as respostas HTTP usam Transfer-Encoding: chunked. Entre elas predominam páginas dinâmicas (60%), respostas de API (25%) e fluxos de mídia (15%). Arquivos estáticos quase sempre usam Content-Length já que seu tamanho é conhecido antecipadamente. A proporção de respostas chunked está diminuindo gradualmente com a adoção de HTTP/2, onde o streaming é implementado no nível de quadro sem a necessidade de um cabeçalho Transfer-Encoding adicional.

Recomendações práticas

No desenvolvimento móvel, use Chunked Transfer para baixar arquivos grandes (imagens, vídeo) e para requisições de API que retornam grandes matrizes de dados. OkHttp suporta completamente chunked transfer sem configuração adicional. Para uploads para o servidor, Chunked Transfer não é usado — HTTP/1.1 não tem Transfer-Encoding para uploads. No iOS, URLSession suporta tanto o envio quanto o recebimento de dados chunked sem configuração especial. A análise JSON em streaming (por exemplo, via Jackson Streaming API ou Moshi) permite processar grandes matrizes JSON à medida que chegam em um fluxo chunked.

Perguntas Frequentes

Como o servidor ativa o Chunked Transfer?

O servidor ativa Chunked Transfer automaticamente quando o tamanho da resposta é desconhecido. Nginx adiciona Transfer-Encoding: chunked se Content-Length não estiver definido. Em Spring Boot, StreamingResponseBody e SseEmitter usam automaticamente chunked transfer. Em Node.js Express, a resposta se torna chunked se res.write() e res.end() forem chamados sem Content-Length.

Content-Length e chunked podem ser usados simultaneamente?

Não, a especificação HTTP/1.1 proíbe o uso simultâneo de Content-Length e Transfer-Encoding: chunked. Se o servidor enviar ambos os cabeçalhos, o cliente deve ignorar Content-Length e processar a resposta como chunked. Esta regra é estabelecida na RFC 7230 para compatibilidade com servidores proxy que podem modificar o corpo da resposta.

Qual é o tamanho ideal de chunk?

O tamanho ideal do chunk depende do cenário. Para páginas web comuns — 4-8 KB. Para streaming de vídeo — 16-64 KB. Para SSE — chunks mínimos de 1-2 KB para reduzir latência. O tamanho do chunk deve ser múltiplo do tamanho do segmento TCP (1460 bytes para Ethernet) para minimizar fragmentação no nível de transporte.

Chunked Transfer funciona através de proxies?

Servidores proxy modernos (Nginx, HAProxy, Envoy) suportam Chunked Transfer. O proxy pode encaminhar chunks sem buffer (streaming) ou armazenar em buffer a resposta inteira e reenviá-la com Content-Length. Proxies antigos podem armazenar em buffer a resposta chunked até a conclusão, aumentando a latência. HTTP/2 resolve este problema no nível do protocolo.

Como Chunked Transfer difere de HTTP chunked encoding?

São a mesma coisa. Chunked Transfer é o nome completo do mecanismo da especificação HTTP/1.1. HTTP chunked encoding é o mesmo, às vezes usado na documentação de bibliotecas. Transfer-Encoding: chunked é o cabeçalho que ativa este modo. Todos os três termos descrevem o mesmo mecanismo de transmissão de dados em partes.

Resumo

  • Chunked Transfer — um mecanismo HTTP/1.1 que transmite o corpo da resposta em chunks sem especificar previamente Content-Length.
  • Transfer-Encoding: chunked — o cabeçalho que ativa a transferência por chunks; cada chunk contém um tamanho hex, dados e CRLF.
  • Um chunk de terminação de tamanho zero sinaliza o fim da transmissão, após o qual cabeçalhos trailer podem seguir.
  • Streaming de conteúdo dinâmico — o caso de uso principal: páginas dinâmicas, SSE, áudio/vídeo em streaming, relatórios longos.
  • Content-Length e chunked são mutuamente exclusivos — a especificação proíbe o uso simultâneo destes cabeçalhos.
  • Vantagens — latência reduzida, economia de memória, capacidade de transmitir fluxos infinitos e processamento em streaming no lado do cliente.
  • Limitações — sobrecarga dos cabeçalhos de chunk, incapacidade de mostrar progresso, problemas com servidores proxy antigos.

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também