skip to content

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%

answer

  1. most specific match wins, not highest q
  2. exact+params > exact > type/* > */*
  3. '*/*, text/html;q=0.2' downgrades HTML to 0.2
  4. params before ;q= are part of the type
  5. ties broken by server quality factor

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.

solid answer

~50 s

Matching is by **specificity, not by best score or list order**. For each representation the server finds the most precise media range that matches and uses that range's q. Precedence, most to least specific: `type/subtype` **with** matching parameters, then plain `type/subtype`, then `type/*`, then `*/*`. With `Accept: */*;q=0.1, text/*;q=0.5, text/html;q=0.7`, a `text/html` body matches all three but takes 0.7; `text/plain` matches the last two and takes 0.5; `image/png` takes 0.1. Specificity binds even when it lowers the score: `Accept: */*, text/html;q=0.2` scores HTML at **0.2**, not 1 — that header means "anything, but preferably not HTML". Parameters count as part of specificity, so `text/html;level=1;q=0.9` matches only a representation carrying `level=1`; plain `text/html` falls through to the next range. When two candidates tie, the server breaks the tie with its own quality factor or its configured default.

code

http · 1 line
http
GET /resource HTTP/1.1\nHost: api.example.com\nAccept: */*, text/html;q=0.2

go deeper

for a junior

It is enough to know the most specific matching entry decides, and to name the ladder exact > type/* > /.

for a middle

Work the '/, text/html;q=0.2' example out loud and explain why specificity is evaluated before magnitude.

for a senior

Bring in server quality factors, tie-breaking policy, and the divergence between browser and SDK Accept headers as a real source of production bugs.

for a principal

Argue about how much negotiation complexity belongs in a service at all versus distinct URLs or an explicit format parameter, and what that costs in caching and support.

## The rule in one line\n\nA representation's weight is the q of the **most specific matching media range**, not the largest q among matching ranges and not the first one listed.\n\n## Media ranges and their specificity order\n\nAn `Accept` entry is a *media range* — a media type where the subtype, or both type and subtype, may be the wildcard `*`. Ranked from most to least specific:\n\n1. `type/subtype;param=value` — exact type with parameters\n2. `type/subtype` — exact type, no parameters\n3. `type/*` — any subtype of a type\n4. `*/*` — anything\n\nFor each representation the server can produce, it walks this ladder and stops at the first rung that matches; that rung's q becomes the representation's client weight.\n\n## Worked example\n\n`Accept: */*;q=0.1, text/*;q=0.5, text/html;q=0.7`\n\n- `text/html` matches `text/html` (rung 2) → **0.7**\n- `text/plain` matches `text/*` (rung 3) → **0.5**\n- `application/json` matches only `*/*` → **0.1**\n\nHTML wins. Note the list order was least-specific-first here and made no difference.\n\n## Specificity can *lower* a score — the counterintuitive case\n\n`Accept: */*, text/html;q=0.2` does **not** mean "everything is fine and HTML is a bonus". `*/*` is q=1 by default, but `text/html` is more specific, so an HTML response scores **0.2** and every other type scores 1. The header means "send me anything except, preferably, HTML". Candidates who assume "take the highest matching q" get this backwards, and it is exactly why interviewers ask.\n\nThe extreme version is refusal: `Accept: */*, image/gif;q=0` accepts every type **except** GIF. Under a highest-match rule GIF would score 1; under the correct specificity rule it is refused.\n\n## Parameters\n\nParameters other than q are part of the media type and part of matching. `text/html;level=1;q=0.9` matches only a representation whose type carries `level=1`. A plain `text/html` representation does not match that range at all and falls through to whatever less specific range applies. This is why `charset` in `Accept` is delicate: `text/html;charset=utf-8;q=1, text/html;q=0.5` scores a UTF-8 HTML document at 1 and a Latin-1 one at 0.5. Note the ordering *within* a range: `q` is the separator between media-type parameters (before it) and negotiation extension parameters (after it), so anything meant as part of the type must precede `;q=`.\n\n## Ties and the server's own weighting\n\nHTTP does not force a winner when two candidates tie. Servers hold a *server quality factor* per representation — Apache's `mod_negotiation` calls it `qs` in a type map, and the effective score is the product of the client q and the server qs. So with `text/*;q=0.5` matching both `text/plain` (qs 0.3) and `text/html` (qs 1.0), HTML wins on the server's own judgement. In an API you usually do the equivalent by hand: sort acceptable types by client q, break ties by a fixed server preference list, and fall back to a documented default.\n\n## Implementation traps\n\nNaive parsers do one of three wrong things: pick the first matching entry; pick the highest matching q; or compare the raw entry string (including `;q=0.8`) to a media type and never match. A correct parser tokenises each entry into type, subtype, parameters and q; for a candidate, filters to matching ranges; and selects the match with the highest specificity rank, using q only after specificity is settled. Many web frameworks ship a tested implementation — prefer it over a hand-rolled `split(',')`.\n\n## Why it matters in production\n\nBrowsers send broad, wildcard-heavy `Accept` headers; SDKs send narrow ones. If your content negotiation is specificity-incorrect, the two classes of client diverge silently: the SDK gets JSON, the browser gets an HTML error page or vice versa, and the bug surfaces only in a support ticket. Pin the behaviour with tests that assert the chosen type for a handful of realistic headers, including the `*/*, text/html;q=0.2` shape.

  • What does 'Accept: */*, image/gif;q=0' mean?
    It accepts every media type except GIF. The wildcard defaults to q=1, but `image/gif` is the more specific match for a GIF representation, so GIF takes q=0 and is refused. Specificity is resolved before the weights are compared, which is what makes an explicit refusal possible at all.
  • How does a server break a tie when two representations end up with the same client q?
    With its own quality factor for each representation — a per-variant score reflecting fidelity or cost — typically multiplied by the client q. Apache exposes this as `qs` in type maps. Hand-written APIs usually encode it as a fixed server preference order with a documented default type.

saying these in an interview costs you the question

  • Saying the highest matching q wins regardless of specificity
  • Saying the first matching entry in the list wins
  • Not realising a specific range can lower a candidate below a wildcard
  • Treating parameters like level or charset as ignorable noise
  • Hand-rolling a comma-split parser and calling it compliant

context