skip to content

questions

16

In HTTP, what is the Accept request header for, and what is a server expected to do with it?

level: juniorimportance: must knowfreq 62%

answer

  1. Accept = what I can read back
  2. Content-Type = what these bytes are
  3. media range: type/subtype, type/*, */*
  4. no Accept ≈ */*
  5. negotiated ⇒ Vary: Accept

basics

~20 s

Accept is a request header listing the media types a client can handle, such as application/json or text/html. The server picks one representation of the resource from that list and names its choice in the response Content-Type header.

solid answer

~50 s

`Accept` is how a client tells the server **which media types it can understand in the response body**. It is a comma-separated list of media ranges, e.g. `Accept: application/json, text/html`. This is *proactive (server-driven) content negotiation*: one URL may have several representations and the server chooses one. The server intersects what the client accepts with what it can produce, picks the best match, and answers with `Content-Type` naming the chosen type. `Content-Type` on the response is the answer to `Accept` on the request. Two things trip people up. First, `Accept` describes the **response**; the `Content-Type` a client sends describes its own **request body** — opposite directions. Second, `Accept` is advisory: a server may ignore it and serve a default. If the response really was negotiated, the server should send `Vary: Accept` so a shared cache doesn't hand a JSON body to an HTML-only client.

code

http · 10 lines
http
GET /users/42 HTTP/1.1
Host: api.example.com
Accept: application/json, text/html

HTTP/1.1 200 OK
Content-Type: application/json
Vary: Accept
Content-Length: 41

{"id":42,"name":"Ada","role":"engineer"}

go deeper

for a junior

Know the one-liner: Accept says what I can receive, response Content-Type says what I got. Give a JSON/HTML example.

for a middle

Add the mechanics: media ranges and wildcards, absent Accept means /, and Vary: Accept for caches.

for a senior

Frame it as proactive negotiation with an advisory contract, discuss client robustness (always read Content-Type) and the CDN cache-poisoning failure mode when Vary is missing.

for a principal

Discuss whether to negotiate at all — many teams pin one representation per URL for cacheability and debuggability, and reserve Accept negotiation for image formats or API versioning where the payoff is concrete.

## The problem it solves One URL can stand for a resource with several *representations*: `/users/42` might be renderable as JSON, as XML, or as an HTML page. Choosing among them is **content negotiation**. In the *proactive* (server-driven) form defined by RFC 9110, the client states its capabilities up front in `Accept`-family request headers and the server decides. ## Syntax `Accept` carries a comma-separated list of **media ranges**. Each range is `type/subtype` optionally followed by parameters after semicolons: ``` Accept: application/json, text/html, image/*, */* ``` `type/subtype` is an exact media type. `type/*` matches any subtype of that type. `*/*` matches anything. Ranges may also carry weights (`;q=…`) which express relative preference; weights are a topic of their own, and everything below holds when no weights are present. An absent `Accept` header means the client accepts anything — it is equivalent to `Accept: */*`, not an error. ## What the server does with it 1. Determine the set of representations it can produce for that resource (JSON only, or JSON + XML + HTML…). 2. Discard those the client did not accept. 3. Among the survivors, choose one — using the client's stated preference first, then its own preference as a tiebreaker. 4. Send the chosen representation with a `Content-Type` header that names exactly what was sent. Step 4 is the part candidates forget. The response is not self-describing without `Content-Type`; the client should read the actual `Content-Type`, not assume the server honoured its first choice. If nothing survives step 2, the server has two legitimate options — refuse with `406 Not Acceptable`, or ignore `Accept` and send its default. Which one real servers pick is a separate discussion. ## Direction matters: Accept vs Content-Type - Request `Accept: application/json` → "send me JSON back." - Request `Content-Type: application/json` → "the bytes I am sending you *are* JSON." - Response `Content-Type: application/json` → "the bytes I am sending you are JSON." There is no `Accept` header on a response. A POST commonly carries both: `Content-Type` for the body it sends, `Accept` for the body it wants back, and they need not be the same (`Content-Type: application/x-www-form-urlencoded` with `Accept: application/json` is ordinary). ## The Accept family The same request-side pattern repeats for other axes of negotiation: `Accept-Language` for natural language, `Accept-Encoding` for compression, and the obsolete `Accept-Charset`. Each has a matching response header that reports what was actually chosen — `Content-Language`, `Content-Encoding`. ## Caching A negotiated response is only valid for clients that sent a compatible `Accept`. The server signals that with: ``` Vary: Accept ``` This tells shared caches to key the stored entry on the request's `Accept` value. Omitting it is a classic production bug: the first request warms the cache with JSON and an HTML-only browser is later served that JSON from the CDN. ## What Accept is really used for in practice - **APIs** that emit JSON by default but can emit XML, CSV, or a problem document. - **Browsers**, which send a long list like `text/html,application/xhtml+xml,image/avif,image/webp,*/*` so a server can return AVIF to a modern browser and JPEG to an old one from the same URL. - **Versioned APIs** using vendor media types such as `application/vnd.example.v2+json`. ## What it is not It is not a field filter (that is a query parameter concern), not a compression control (`Accept-Encoding` does that), and not binding on the server. A server that only ever produces JSON is entitled to produce JSON regardless of what `Accept` says — many do exactly that, and clients must tolerate it.

  • What does a server do if the request has no Accept header at all?
    An absent Accept means the client has no stated preference and will take anything — it is treated as `*/*`. The server should serve its default representation, not an error. Returning 406 because the header is missing is a bug.
  • Why should a negotiated response carry Vary: Accept?
    Because the response body depends on a request header, a shared cache must not reuse it for a request whose Accept differs. `Vary: Accept` makes Accept part of the cache key. Without it a CDN can serve the JSON representation to a client that asked only for HTML.
  • If a client sends Accept: application/json and the server sends back text/html, what should the client do?
    Read the response Content-Type and handle it — Accept is a preference, not a contract. A robust client checks the actual Content-Type before parsing, and treats an unexpected type as an error case rather than blindly feeding an HTML error page to a JSON parser.

Accept is the diner saying "I can eat anything vegetarian or fish"; Content-Type is the waiter putting down the plate and saying "this is the sea bass". The kitchen may still bring something off-list.

saying these in an interview costs you the question

  • Saying Accept and Content-Type are the same header or interchangeable.
  • Claiming Accept describes the request body being sent.
  • Insisting the server MUST return one of the listed types or fail.
  • Thinking a missing Accept header is an error worth rejecting.
  • Never mentioning that the response's own Content-Type reports the actual choice.

context

open as a page

Walk through how HTTP response compression is negotiated between a client and a server using the Accept-Encoding and Content-Encoding headers.

level: juniorimportance: must knowfreq 58%

basics

~20 s

The client sends Accept-Encoding listing codings it can decode, such as gzip, br, zstd. The server may compress the body with one of them and must say which in Content-Encoding. The client decompresses before parsing. Uncompressed is called identity.

open as a page

In HTTP content negotiation, what does the q= parameter mean in a request header such as 'Accept: text/html;q=0.8, application/json', and what value applies when you leave it out?

level: juniorimportance: must knowfreq 52%

basics

~20 s

q is a relative preference weight from 0 to 1 (three decimals max). Omitted means q=1, the strongest preference; q=0 means unacceptable. So in that header application/json (q=1) is preferred over text/html (0.8). Header order carries no priority.

open as a page

What is the difference between HTTP status 406 Not Acceptable and HTTP status 415 Unsupported Media Type?

level: middleimportance: must knowfreq 54%

basics

~20 s

406 is about the response: the server cannot produce any representation matching the request's Accept headers. 415 is about the request body: the server cannot process the Content-Type (or Content-Encoding) the client sent. Response side versus request side.

open as a page

A client POSTs a JSON body but sends no Content-Type header, or sends `Content-Type: text/plain`. Why do many HTTP servers answer 415 Unsupported Media Type, and what should that response include?

level: juniorimportance: should knowfreq 42%

basics

~20 s

The server routes a body by its declared Content-Type, not by sniffing the bytes. With no Content-Type or the wrong one, there is no parser to hand it to, so it returns 415 — ideally with an Accept-Post header naming the media types it accepts.

open as a page

How does the HTTP Accept-Language header work, and why is the Accept-Charset header effectively obsolete?

level: middleimportance: should knowfreq 36%

basics

~20 s

Accept-Language lists language tags such as en-GB or fr that a client prefers for the response; the server picks a translation and reports it in Content-Language. Accept-Charset is obsolete because everything is UTF-8 now, so browsers stopped sending it.

open as a page

A client sends `Accept: text/html, text/*, */*` in an HTTP request. Explain what the wildcards `text/*` and `*/*` mean and how a server decides which media type to serve.

level: middleimportance: should knowfreq 45%

basics

~20 s

They are media ranges of decreasing specificity: an exact type, any subtype of text, then anything. A server matches its available representations against them and the most specific matching range wins, so an HTML representation is preferred here.

open as a page

Compare gzip, Brotli (br) and Zstandard (zstd) as HTTP content codings. When would you choose each?

level: middleimportance: should knowfreq 40%

basics

~20 s

gzip is the universal baseline — modest ratio, fast, supported everywhere. Brotli compresses text best, especially precompressed at high levels, but is slow to compress at high settings. zstd compresses near-Brotli quality far faster, making it good for dynamic responses; browser support is the newest.

open as a page

An HTTP client sends 'Accept: */*;q=0.1, text/*;q=0.5, text/html;q=0.7'. Explain how a server decides the weight for a candidate text/html response versus a candidate text/plain response when more than one entry matches.

level: middleimportance: should knowfreq 34%

basics

~20 s

Each candidate takes the weight of the most specific matching entry, not the highest or the first. Precedence: exact type/subtype with parameters, then type/subtype, then type/*, then /. So text/html scores 0.7 and text/plain scores 0.5; text/html wins.

open as a page

What are vendor media types such as `application/vnd.github+json` in an HTTP Accept header, and how are they used to select an API version?

level: seniorimportance: should knowfreq 34%

basics

~20 s

They are media types in the vendor registration tree (vnd.) naming an organisation's own format, usually with a structured suffix like +json. A client asks for one in Accept, e.g. application/vnd.example.v2+json, and the server returns that variant and echoes it in Content-Type.

open as a page

What is the difference between the HTTP Content-Encoding and Transfer-Encoding headers?

level: seniorimportance: should knowfreq 34%

basics

~20 s

Content-Encoding is end-to-end: it transforms the representation itself, so only the final recipient decodes it and caches store it encoded. Transfer-Encoding is hop-by-hop framing for one connection — chunked is its only real use — and it does not exist in HTTP/2 or HTTP/3.

open as a page

How do you serve pre-compressed static assets over HTTP — for example .br and .gz files written at build time — and what must be correct for caches and proxies?

level: seniorimportance: should knowfreq 28%

basics

~20 s

Build both a .br and .gz copy beside each asset. The server checks Accept-Encoding, serves the matching file with the original Content-Type, the right Content-Encoding, Vary: Accept-Encoding, a distinct ETag per encoding, and falls back to the uncompressed file.

open as a page

When a client's HTTP Accept header cannot be satisfied, a server may return 406 Not Acceptable or ignore the header and send a default representation. Which do real servers do, and why?

level: seniorimportance: should knowfreq 32%

basics

~20 s

Most servers ignore an unsatisfiable Accept header and send their default representation, because a 406 is usually less useful than a body the client can inspect and because Accept headers are frequently wrong or over-narrow. 406 is reserved for genuinely strict negotiation.

open as a page

What does a quality value of zero mean in HTTP request headers such as 'Accept-Encoding: gzip, identity;q=0', and how would you design server-side selection when Accept, Accept-Language and Accept-Encoding weights disagree about which stored representation is best?

level: seniorimportance: should knowfreq 24%

basics

~20 s

q=0 means explicitly unacceptable — 'identity;q=0' forbids an uncompressed body. Each Accept-* header is an independent axis; the server scores each representation per axis, combines with fixed axis priority or multiplication plus its own quality factors, and must emit Vary listing every header it negotiated on.

open as a page

An API endpoint starts returning HTTP 406 Not Acceptable to some clients in production. How do you diagnose and fix it?

level: seniorimportance: nice to knowfreq 24%

basics

~20 s

Capture the exact Accept, Accept-Language and Accept-Encoding headers the server actually received, compare them with the representations the server can produce, and find what changed — usually a proxy rewriting Accept or a removed serialiser. Fix by restoring the representation or relaxing to a default.

open as a page

How would you set a compression policy for a service sitting behind a CDN — what gets compressed, at which layer, and at what cost?

level: principalimportance: nice to knowfreq 26%

basics

~20 s

Compress text-like types above a size threshold, never already-compressed media; precompress static assets at maximum level and use a fast coding for dynamic ones; do it in exactly one layer; and exclude responses that mix secrets with attacker-influenced input.

open as a page