Question 17 · Section 6

What is Accept header?

The server returns 406 Not Acceptable — "I can't respond in the format you're asking for".

Language versions: English Russian Ukrainian

Junior Level

Accept is an HTTP header that tells the server in what format the client wants to receive the response.

Examples:

Accept: application/json        — I want JSON
Accept: application/xml         — I want XML
Accept: text/html               — I want HTML
Accept: */*                     — any format is fine

Difference from Content-Type:

  • Content-Type — format of data I’m sending
  • Accept — format of data I want to receive

Request example:

GET /users/1
Accept: application/json

// Server response:
{"id": 1, "name": "Ivan", "age": 30}

What happens if the server doesn’t support the requested format?

The server returns 406 Not Acceptable — “I can’t respond in the format you’re asking for”.


Middle Level

Content Negotiation in Spring

Content negotiation algorithm:

  1. Client sends Accept: application/json
  2. Spring looks for controller methods with produces = "application/json"
  3. Checks for an HttpMessageConverter that can write this type
  4. If no match — returns 406 Not Acceptable

Quality coefficients (q-values)

The Accept header supports priority weights:

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
  • text/html — priority 1.0 (default)
  • application/xml — priority 0.9
  • */* (everything else) — 0.8
    • In the example above, */* has q=0.8 — this is a specific browser’s value. The client can set any q from 0.0 to 1.0.

Why? This enables Graceful Degradation — if the server can’t serve the preferred format, it will serve an alternative. A mobile app requests application/json;q=1.0 and text/plain;q=0.5.

Performance and Caching

The Vary Header

If an endpoint returns different formats (JSON/XML) on the same URL depending on Accept, RFC 7231 requires returning Vary: Accept if the content depends on this header and the response may be cached. Without Vary, CDN/proxies may serve the wrong format.

Why? So that the cache (Nginx/CDN) doesn’t serve a JSON response to a user who requested XML.

Edge Cases

  • Accept-Charset and Accept-Encoding: Don’t confuse them. Accept — about data format, Accept-Charset — about encoding, Accept-Encoding — about compression (gzip/brotli)
  • Browser Wildcards: Browsers often send Accept: */*. Spring will choose the first suitable converter (usually JSON)

Diagnostics

  • 406 Not Acceptable Analysis: Spike in 406s = client requests a format you haven’t implemented (or you accidentally removed a converter)
  • ContentNegotiationManager: Can configure priority: path extension (.json) → query parameter (?format=json) → Accept header. At the Senior level, it’s recommended to rely only on headers

Senior Level

When Accept header is not needed

  1. API with a single fixed format (JSON only)
  2. Internal microservices — format is fixed by contract
  3. When Content Negotiation adds overhead without benefit

Content Negotiation — deep dive

Content Negotiation is the process by which the server determines the best response format for the client.

Spring ContentNegotiationManager

You can configure selection priority:

  1. Path extension (.json)
  2. Query parameter (?format=json)
  3. Accept header

Recommendation: At the Senior level, rely only on headers. Path extensions and query parameters create caching and URL semantics problems.

Vendor MIME Types for versioning

Using application/vnd.mycompany.v1+json is a great versioning approach:

  • Allows caching different API versions under a single URI
  • If the cache respects the Accept header, different versions won’t get mixed up

Performance

  • Vary: Accept is recommended when supporting multiple formats — without it, the CDN may serve the wrong format from cache
  • Vendor MIME Types allow versioning each entity independently
  • Negative Caching: CDN can cache 406 responses, protecting the backend from repeated requests for unsupported formats

Diagnostics and Monitoring

  • 406 Analysis: A spike in 406s means the client updated and is requesting a format you haven’t implemented yet
  • Converter Order: The order of converter registration matters — Spring picks the first match
  • Browser Behavior: Browsers often send Accept: */*, which can lead to unexpected format selection. Test with real User-Agent headers

Interview Cheat Sheet

Must know:

  • Accept tells the server the format the client wants to receive: application/json, application/xml
  • Content-Type = what I’m sending, Accept = what I want to receive
  • q-values (quality coefficients): Accept: application/json;q=1.0,text/plain;q=0.5 — priorities from 0.0 to 1.0
  • 406 Not Acceptable — server doesn’t support the requested format
  • Vary: Accept is mandatory when supporting multiple formats — without it, CDN serves the wrong format from cache
  • Vendor MIME Types (application/vnd.mycompany.v1+json) — API versioning approach
  • Spring ContentNegotiationManager: priority — path extension → query parameter → Accept header

Common follow-up questions:

  • What does Vary: Accept do? — Tells the cache that the response depends on the Accept header; without Vary, CDN serves JSON instead of XML
  • Why are q-values needed? — Graceful Degradation: if the server can’t serve the preferred format, it serves an alternative
  • Why shouldn’t extensions (.json) be used for Content Negotiation? — They create caching and URL semantics problems
  • How to version via Accept? — Vendor MIME Types: application/vnd.myapi.v2+json, cache respects Accept

Red flags (DO NOT say):

  • “Accept and Content-Type are the same” — Accept = expected response, Content-Type = request format
  • “Browsers always send a specific Accept” — browsers often send Accept: */*
  • “406 is a server error” — 406 = client requests a format the server doesn’t support
  • “Vary: Accept isn’t needed” — without Vary, CDN may serve a JSON response to a client that requested XML

Related topics:

  • [[What is Content-Type header]]
  • [[How to organize REST API versioning]]
  • [[What HTTP status codes do you know]]
  • [[What is REST]]
  • [[What is HATEOAS]]