Content Negotiation: eine URL, für jeden die beste Antwort

Stand: Juli 2026

Hinter den modernen Auslieferungs-Tricks — AVIF/WebP für Bilder, Brotli für Assets — steckt ein und dasselbe Prinzip, und es ist keine Erfindung der CDN-Ära: Content Negotiation ist Standard-HTTP, seit 1997 in HTTP/1.1 spezifiziert. Die Idee: Eine URL hat nicht eine richtige Antwort, sondern mehrere — und Browser und Server handeln bei jeder Anfrage aus, welche die beste ist.

Das Entscheidende für jeden, der über Shop-Architektur nachdenkt: Die Verhandlung passiert unsichtbar in der Auslieferungsschicht. Keine URL ändert sich, kein Quellsystem muss neue Formate lernen, kein JavaScript rät am Client herum. Genau deshalb ist Content Negotiation das Werkzeug der Wahl, wenn ein Altsystem im Stack nicht mitzieht — man verhandelt einfach eine Etage weiter vorn.

Der Mechanismus: Bestellzettel und Lieferschein

Jede Browser-Anfrage trägt Kopfzeilen, die wie ein Bestellzettel sagen, was der Client versteht:

GET /media/angelrute.jpg
Accept: image/avif,image/webp,image/*        ← „Ich kann AVIF und WebP"
Accept-Encoding: br, gzip                    ← „Ich kann Brotli und gzip"
Accept-Language: de-DE, de                   ← „Ich hätte gern Deutsch"

Der Server (oder das CDN) wählt daraus die beste verfügbare Variante und antwortet mit einem Lieferschein, der zwei Dinge festhält — was geliefert wurde und wovon die Wahl abhing:

200 OK
Content-Type: image/avif                     ← das hast du bekommen
Content-Encoding: br                         ← so ist es verpackt
Vary: Accept, Accept-Encoding                ← die Antwort hängt von diesen Headern ab

Vary: die wichtigste Zeile des Systems

Der Vary-Header ist die Stelle, an der Content Negotiation und Caching sich treffen — und die Stelle, an der es in der Praxis knirscht. Er sagt jedem Cache auf dem Weg (Varnish, CDN, Browser): Speichere pro Wert dieses Headers eine eigene Variante. Ein Cache, der Vary: Accept-Encoding respektiert, hält für dieselbe URL eine Brotli-, eine gzip- und eine unkomprimierte Fassung — und liefert jedem Client die passende.

Daraus folgen die beiden Praxis-Regeln:

1. Ohne Vary (bzw. passenden Cache-Schlüssel) ist Content Negotiation gefährlich: Der Cache liefert dem Uralt-Browser das AVIF des Chrome-Nutzers. Deshalb muss der verhandelte Header in den Cache-Schlüssel — bei CloudFront über die Cache-Policy, bei Varnish über Normalisierung + Hash.
2. Mit ungezähmtem Vary zersplittert der Cache: Browser schicken Dutzende Accept-Encoding-Spielarten — wer sie nicht auf zwei, drei Stufen normalisiert, cached jede Spielart einzeln und ruiniert seine Quote. Verhandelt wird über wenige, klar definierte Varianten — nie über den rohen Header-Wildwuchs.

Warum nicht einfach andere URLs oder JavaScript?

Die Alternativen existieren — und verlieren beide:

  • Separate URLs (bild.webp, bild.avif, <picture>-Markup): funktioniert, aber jetzt müssen alle URLs-erzeugenden Systeme mitspielen — Templates, CMS-Inhalte, Feeds, und ja: die Warenwirtschaft. Genau die Systeme, die man nicht anfassen kann oder will. Content Negotiation lässt alle URLs, wie sie sind.
  • JavaScript-Detection (Format testen, Bild nachladen): kostet einen Roundtrip, flackert, ist unsichtbar für Caches und Crawler — und der Feed-Reader oder Merchant-Bot führt gar kein JavaScript aus.

Die Verhandlung über Header ist die einzige Variante, die cache-freundlich, crawler-sicher und quellsystem-neutral zugleich ist.

Dieselbe Mechanik, zwei Produktiv-Fälle

BildformateAsset-Kompression
Verhandelt überAcceptAccept-Encoding
VariantenAVIF / WebP / JPEGbr / gzip / roh
Erzeugungon-the-fly im CDN + Edge-Cache (Bestand zu groß für Vorab)vorkomprimiert beim Deploy (klein, ändert sich nur beim Release)
Gewinnbis zu −80 % Bildgröße−23 % gegenüber gzip
DetailsUse Case BildformateUse Case Brotli-Assets

Zum Selbst-Prüfen reicht curl — einmal mit, einmal ohne Fähigkeit anfragen und die Lieferscheine vergleichen:

curl -sI -H 'Accept-Encoding: br'   https://shop.example/theme/all.css | grep -iE 'content-encoding|vary'
curl -sI -H 'Accept-Encoding: gzip' https://shop.example/theme/all.css | grep -iE 'content-encoding|vary'

Antwortet die erste Zeile mit content-encoding: br und die zweite mit gzip, verhandelt die Auslieferung sauber — dieselbe URL, für jeden Client die beste Antwort.