Curl Custom Headers Example

A custom header is one an application defines for itself: an API version, an idempotency key, a tenant, a request id. Curl sends them like any other header; the questions worth answering are what they are for and what happens to them on the way.

Last updated . How this page is checked.

The command

curl https://httpbin.org/anything \
  -H "X-Api-Version: 2" \
  -H "Idempotency-Key: 8e03978e-40d5-43e8-bc93-6894a57f9324" \
  -H "X-Tenant: acme"

Opens the request console with this request filled in. It is sent from api-tester.com's server rather than from your machine, so it shows what the endpoint returns, not how your own network or curl build behaves.

What the flags do

FlagWhat it does
-H "X-Name: value"Send an application-defined header. Repeat the flag for each one.
-H "X-Name: a" -H "X-Name: b"Sends the header twice. Curl does not merge or de-duplicate what you give it.
--proxy-header "Name: value"A header for the proxy only, not for the destination server.
-D fileSave the response headers, which is where a request id usually comes back.

What custom headers are for

Four jobs account for most of them. A version header pins the behaviour of an API so a later release does not change your results. An idempotency key lets you repeat a POST after a timeout without creating a second record. A request or trace id ties your call to a line in the server's logs, and is the first thing a support team will ask for. A tenant or feature header selects which account or code path handles the call.

The server chooses the names. A header it does not recognise is not an error; it is ignored, and you get default behaviour with no warning.

# send a request id and read it back from the response headers
curl -s -o /dev/null -D - "https://httpbin.org/response-headers?X-Request-Id=7f3a9c" \
  -H "X-Request-Id: 7f3a9c" | grep -i "^x-request-id"

Names, case and size

Header names are case-insensitive, and on HTTP/2 they are transmitted in lower case whatever you typed, so X-Api-Version and x-api-version are one header. Stick to letters, digits and hyphens: several reverse proxies discard names containing an underscore before the application sees them. Values should be plain ASCII on one line.

Servers also cap the total size of a request's headers, typically at a few kilobytes. A long token plus a large cookie can cross that limit and produce a 431 or a bare 400 that has nothing to do with the request body.

curl -s --http1.1 https://httpbin.org/headers -H "x-api-version: 2"
curl -s --http2   https://httpbin.org/headers -H "X-Api-Version: 2"

Why it works in curl and fails in a browser

Curl sends whatever you ask. A browser first checks with the server: any header outside a short safelist makes a cross-origin request "non-simple", so the browser sends an OPTIONS preflight and proceeds only if the reply lists your header in Access-Control-Allow-Headers. An API can therefore accept a custom header from curl and still be unusable from a web page. Sending the preflight yourself shows which it is; the CORS example goes through the reply line by line.

curl -s -i -X OPTIONS https://httpbin.org/anything \
  -H "Origin: https://app.example.com" \
  -H "Access-Control-Request-Method: GET" \
  -H "Access-Control-Request-Headers: x-api-version, idempotency-key" \
  | grep -i "^access-control"

Common mistakes

  • A misspelt custom header fails silently. Compare the name with the documentation character by character before suspecting anything else.
  • An idempotency key belongs to one request. Reusing it with a different body gets the first response replayed, or an error.
  • The X- prefix carries no meaning. It is a habit, not a rule, and an API is free to name a header without it.

Related curl examples

More under Headers

References

  • curl man page: -H — Adding request headers, including application-defined ones.
  • MDN: CORS — Why a custom header makes a browser send a preflight request.

These links leave api-tester.com, which is independent of the projects they point to.

FAQ

How do I add a custom header in curl?

Use -H with the header name and value, for example curl -H "X-Api-Version: 2" URL. Add another -H for each further header.

Do custom headers need an X- prefix?

No. The prefix is a long-standing convention, not a requirement. Use exactly the header names the API documents.

Are HTTP header names case-sensitive?

No. Header names are case-insensitive, and HTTP/2 always sends them in lower case. Header values can be case-sensitive, depending on the header.