How curl handles chunked transfer encoding uploads
This article explains how the curl command-line tool
manages chunked transfer encoding during data uploads. It covers when
curl automatically applies chunked encoding, how the
underlying data transfer mechanism works, and how to force or disable
this behavior during HTTP requests.
When curl Uses Chunked Transfer Encoding
By default, when you upload a file using curl with the
-T (or --upload-file) option,
curl attempts to determine the file size beforehand. If it
can determine the size, it sends a standard Content-Length
header. However, curl automatically switches to chunked
transfer encoding under the following conditions:
- Streaming from Standard Input (stdin): When you
pipe data into
curlusing-T -,curlcannot know the total size of the incoming stream in advance. To stream this data in real-time without buffering the entire payload into memory,curladds theTransfer-Encoding: chunkedheader. - Explicit Headers: If you manually specify the
header using
-H "Transfer-Encoding: chunked",curlwill format the outgoing request body using chunked encoding.
How the Data is Transmitted
When chunked transfer encoding is active, curl does not
send the entire payload as a single continuous block. Instead, it breaks
the upload stream into a series of chunks.
Each chunk is formatted with: 1. The size of the chunk represented in hexadecimal format. 2. A carriage return and line feed (CRLF). 3. The actual chunk data. 4. Another CRLF.
Once the entire stream has been read and sent, curl
transmits a final chunk of size zero (0 followed by CRLF)
to signal to the receiving server that the upload is complete.
Forcing or Disabling Chunked Uploads
If you are uploading a static file but want to force chunked encoding—often done to test how a receiving server handles chunked requests—you can manually add the header to your command:
curl -H "Transfer-Encoding: chunked" -T localfile.txt http://example.com/upload
Conversely, if a target server does not support chunked encoding and
rejects the upload, you must avoid streaming. You can resolve this by
uploading a physical file directly so curl can calculate
the Content-Length before transmitting, or by buffering
your stream to a temporary local file before initiating the upload.