Skip to content

Calculate the overhead of multipart/form-data accurately

Category: HTTP / Networking

Have you ever experienced a 413 error when a file is only 9MB during file upload size limit testing? One of the causes is the overhead of multipart/form-data. When uploading a file via an HTML form, the HTTP request body contains not only the file itself but also additional metadata. This article explains the precise calculation method for that overhead and points to consider during testing.

Structure of multipart/form-data

multipart/form-data defined in RFC 2046 has a structure where each part is separated by a boundary string. An actual HTTP request body looks like this.

POST /upload HTTP/1.1
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryABC123
Content-Length: 10000xyz

------WebKitFormBoundaryABC123
Content-Disposition: form-data; name="file"; filename="test.png"
Content-Type: image/png

[ファイルのバイナリデータ]
------WebKitFormBoundaryABC123--

Overhead Breakdown

The overhead of a typical file upload request consists of the following elements.

ElementExampleNumber of Bytes (Approximate)
Starting boundary------WebKitFormBoundaryABC123\r\nApproximately 40–80 B
Content-Disposition HeaderContent-Disposition: form-data; name="file"; filename="test.png"\r\nApproximately 60–120 B
Content-Type HeaderContent-Type: image/png\r\nApproximately 25–50 B
Blank line (end of headers)\r\n2 B
Line Break at End of Part\r\n2 B
Closing boundary------WebKitFormBoundaryABC123--\r\nApproximately 42–82 B
Total overheadApproximately 200–350 B

For a simple form with just one file, the overhead is approximately 200–400 bytes. If there are additional form fields (such as text inputs), the overhead increases accordingly, but it typically stays within a few hundred bytes to several kilobytes.

Why does the 413 error occur

Nginx's client_max_body_size limits the size of the entire request body. In other words, the configured value must include overhead.

# 10MiB のファイルをアップロードさせたい場合
# オーバーヘッド(約1KB)を考慮して少し大きめに設定
client_max_body_size 11m;  # MiB単位: 11 MiB = 11,534,336 バイト

For PHP, you need to configure two settings: upload_max_filesize (per file) and post_max_size (entire POST body).

; php.ini
upload_max_filesize = 10M   ; ファイル単体の上限: 10 MiB
post_max_size = 11M         ; POSTボディ全体の上限: 11 MiB(オーバーヘッド分を加算)

Accurate overhead measurement method

If you want to know the actual overhead accurately, you can send requests with curl and measure the request size.

# ファイルのバイト数を確認
wc -c test-10mb.png
# → 10485760 test-10mb.png

# curl でアップロードしてリクエストサイズを確認
curl -X POST https://example.com/upload \
  -F "file=@test-10mb.png" \
  -w "リクエストボディサイズ: %{size_upload} バイト\n" \
  -o /dev/null -s
# → リクエストボディサイズ: 10486062 バイト(差: 302バイト)

Difference from Base64 Encoding

With multipart/form-data, binary file data is sent as-is (without Base64 encoding). Base64 encoding is only needed when sending binary with application/x-www-form-urlencoded or sending files in JSON bodies (like data:image/png;base64,...).

Transmission methodOverheadUse case
multipart/form-data (HTML Form)Hundreds of bytes to several KBStandard file upload
JSON + Base64Approximately 33% increaseFile Transfer via API
application/octet-stream(PUT)Nearly zeroS3 presigned URLs and more

Testing considerations

  • Understand whether the server's size limit check is for "individual files" or "entire request body"
  • Since Nginx limits requests before PHP, check Nginx's client_max_body_size as well
  • Simultaneous upload of multiple files increases overhead
  • Overhead also includes additional form fields (name, comment, etc.)

Using the threshold test files on DevLab, you can verify actual upload behavior with file sizes near the boundary. Validate in conjunction with your Nginx/Apache/PHP configuration.

Summary

  • The overhead of multipart/form-data is approximately 200–400 bytes (for a single file)
  • Since Nginx's client_max_body_size limits the entire request body, set it slightly larger than the file size limit
  • PHP requires setting two directives: upload_max_filesize (individual file) and post_max_size (entire POST body).
  • When Sending via JSON + Base64, File Size Increases by Approximately 33%

❓ Frequently Asked Questions

How large is the overhead of multipart/form-data?
For a simple form with a single file it comes to roughly 200-400 bytes: the boundary strings, the Content-Disposition and Content-Type headers, and the line breaks. Extra form fields add more, but the total normally stays between a few hundred bytes and a few kilobytes.
Why do I get a 413 even though the file is under the limit?
Nginx's client_max_body_size limits the entire request body. Once the multipart overhead — boundaries, headers — pushes the total past the configured value, you get a 413. Set client_max_body_size a little above your intended file limit.
Which has more overhead, multipart/form-data or Base64?
Base64 — sending through JSON — is far more expensive: it inflates the file by about 33%. multipart/form-data ships the binary untouched, so its overhead stays between a few hundred bytes and a few kilobytes.