Antwort A
Antwort B

API-Response-Diff: JSON-API-Payloads online vergleichen

Füge die erwartete Antwort links ein, die tatsächlich erhaltene Antwort rechts, und sieh jedes geänderte Feld. Gebaut für Backend-, QA- und Integrationsarbeit. Nichts verlässt deinen Browser.

Was dieses API-Response-Diff-Tool ist

Ein kostenloses, im Browser laufendes Werkzeug zum Vergleichen zweier HTTP-API-Response-Bodys. Füge das JSON aus Staging links ein, das JSON aus Produktion rechts, und die Unterschiede werden Zeichen für Zeichen hervorgehoben. Der Text verlässt deinen Rechner nicht. Das ist wichtig, weil echte API-Antworten regelmäßig Kunden-E-Mail-Adressen, Session-Tokens, interne Benutzer-IDs und andere Dinge enthalten, die du nicht auf einer fremden Diff-Seite hochladen willst.

Es ist für den Moment gebaut, in dem ein flackernder Integrationstest in CI fällt und du auf dem Laptop einen Postman-Screenshot einer funktionierenden Antwort hast und im CI-Log eine kaputte Antwort vom Build-Runner. Einen kompletten Pact-Contract-Test für eine einmalige Untersuchung hochzuziehen ist Overkill. Zwei Textfelder, ein Diff, und meist ist das Problem in unter einer Minute auf ein einzelnes Feld eingegrenzt.

Unter der Haube ist die Diff-Engine dieselbe, die unser compare-json-Tool antreibt. Wir haben sie nur für den API-Test-Workflow eingerahmt. Wenn deine Antworten XML oder SOAP-Envelopes sind, übernimmt das unsere compare-xml-Seite. Wenn du frei formatierten Text wie ein Webhook-Log oder einen Audit-Trail vergleichst, ist unser compare-text-Tool die richtige Anlaufstelle.

Wie ein API-Response-Diff tatsächlich hilft

Ein API-Response-Diff sitzt in der Lücke zwischen zwei verwandten, aber unterschiedlichen Test-Ideen. Schema-Diff für OpenAPI 3.1 sagt dir, was dein Vertrag laut eigener Aussage geändert hat: ein neues optionales Feld, eine umbenannte Property, ein strikteres Enum. Snapshot-Tests (Jest-Snapshots, Vitest-Snapshots, pytest-snapshot) sagen dir, was dein Code produziert hat, gemessen an einer gespeicherten Fixture. Dieses Tool sitzt auf der Runtime-Seite. Du gibst ihm zwei echte Response-Bodys, und es zeigt dir jedes Byte, das sich unterscheidet, unabhängig davon, ob das Schema die Änderung erlaubt oder ob deine Snapshot-Fixture aktuell ist.

Warum ist das nützlich? Weil die Bugs, die in REST-Integrationsarbeit am stärksten beißen, keine Schema-Verletzungen sind. Es sind subtile Drifts: ein Serializer, der nach einem Jackson-Upgrade leise ein Datum von ISO-8601 auf einen Unix-Timestamp umstellt, ein Marshmallow-Schema, das plötzlich null ausgibt statt ein fehlendes Feld wegzulassen, ein DRF-ViewSet, das nach einer Middleware-Änderung anfängt, das Payload in einen data-Envelope zu verpacken. Die OpenAPI-Spec hat sich nicht geändert. Der Snapshot wurde nicht aktualisiert. Die Tests sind isoliert grün. Die Integration ist kaputt. Ein Response-Body-Diff fängt all das ab, weil er sich nicht für den Vertrag interessiert; er interessiert sich für die Bytes.

Volatile Felder sind das Hauptproblem. Timestamps, Request-IDs, Trace-IDs, server-generierte UUIDs und Pagination-Cursor unterscheiden sich zwischen zwei Captures desselben Endpoints, selbst wenn sich nichts Bedeutendes geändert hat. Der richtige Schritt ist, vor dem Diff zu normalisieren: Timestamps durch einen Platzhalter ersetzen, Trace-IDs entfernen, Arrays sortieren, deren Reihenfolge nicht vertraglich relevant ist. Tools wie Pact erledigen das mit Matchern; in diesem Tool erledigst du es, indem du die Felder editierst. Es dauert zehn Sekunden und entfernt das Grundrauschen.

Wie du eine API-Response in drei Schritten diff-st

Zwei Textfelder, ein Diff. Kein Login, kein Upload, kein Proxy zu verkabeln.

  1. 1

    Erste Antwort einfangen

    Triff den Endpoint mit curl, httpie, Postman, Insomnia oder was dein Team nutzt. curl -s https://api.example.com/v1/users/123 | jq ist eine gute Basis, weil jq das JSON formatiert ausgibt, was den Diff deutlich lesbarer macht. Kopiere den Body (nur das JSON, keine Header) und füge ihn ins linke Feld ein. Wenn du aus einem CI-Log ziehst, entferne den Timestamp-Präfix, den die meisten Logger anfügen, damit der Diff auf das eigentliche Payload trifft.

  2. 2

    Zweite Antwort einfangen

    Triff die Vergleichsquelle: die andere Umgebung, die andere API-Version, den anderen Anbieter. Gleiche Form der Erfassung, gleicher Pretty-Print-Schritt. Ins rechte Feld einfügen. Wenn ein Capture aus einer aufgezeichneten Fixture stammt (vcrpy, pollyjs, MSW, nock) und das andere live ist, normalisiere zuerst die offensichtlich volatilen Felder: request_id säubern, Timestamps durch eine Konstante ersetzen und alle Trace-Header entfernen, die in den Body geraten sind. Der verbleibende Diff ist das eigentliche Signal.

  3. 3

    Hervorgehobene Unterschiede lesen

    Löschungen erscheinen links als rote Durchstreichungen; Einfügungen rechts in Grün. Die Änderungszähler in den Headern zeigen, wie viele unterschiedliche Edits der Diff gefunden hat. Konzentriere dich zuerst auf drei Dinge: Änderungen an Status-Strings, fehlende oder hinzugefügte Keys und Wertetyp-Änderungen (string zu number, object zu null). Diese drei Kategorien decken nahezu jede echte API-Regression ab. Format- und Reihenfolgeänderungen sind meist Rauschen, sofern dein Consumer nicht davon abhängt.

Wann ein API-Response-Diff die richtige Wahl ist

Einen flackernden Integrationstest reproduzieren

Ein Test besteht lokal und fällt in CI. Du hast die Antwort, die dein lokaler Postman-Lauf eingefangen hat, und die Antwort des CI-Build-Agenten (die meisten CI-Systeme können Request/Response mit einem Verbose-Flag dumpen). Beides ins Diff-Tool einfügen. Neun von zehn Mal ist der Unterschied umweltbedingt: ein anderer Feature-Flag, eine veraltete Fixture, ein Zeitzonen-Offset auf dem Build-Runner. Der zehnte Fall ist ein echter Bug, und du hast ihn gerade auf ein bestimmtes Feld eingegrenzt.

Eine Fixture gegen eine frische Antwort validieren

In deinem Repo liegt eine eingecheckte Fixture-Datei, die für Tests eine Drittanbieter-API mockt. Der Upstream-Anbieter hat gerade eine neue Minor-Version veröffentlicht. Triff den Live-Endpoint mit curl, füge die Antwort neben deine Fixture ein, und du siehst genau, welche Felder gedriftet sind. Das ist die manuelle Variante dessen, was VCR-artige Replay-Tools automatisieren. Hilfreich, wenn du eine einzelne Fixture aktualisieren willst, ohne die ganze Test-Suite neu aufzunehmen.

Abwärtskompatibilität zwischen API-Versionen prüfen

Du bist kurz davor, v2 einer internen API zu veröffentlichen. Ein v1-Client läuft noch in Produktion. Triff sowohl /v1/orders/42 als auch /v2/orders/42 und diff die Antworten. Jedes entfernte Feld, jeder umbenannte Key, jede Wertetyp-Änderung ist ein Breaking Change für den v1-Client. Jedes neue Feld ist additiv und sicher. Es ist eine Sparversion eines consumer-driven Contract-Tests; skaliert nicht auf Dutzende Endpoints, aber für einen schnellen Sanity-Check an einem oder zwei reicht es.

Eine Serializer-Regression aufspüren

Dein Team hat Jackson, Marshmallow, DRF oder eine ähnliche Serialisierungsschicht aktualisiert. Tests bestehen. Dann meldet ein Downstream-Consumer, dass sein Parser sich verschluckt. Erfasse die Antwort desselben Endpoints im alten und im neuen Branch und diff sie. Häufige Funde: ein Datumsformat ist von 2026-05-09T10:00:00Z auf einen Unix-Timestamp gekippt, Dezimalstellen haben nachfolgende Nullen verloren, ein Enum wird plötzlich als Integer statt String serialisiert, oder null-Felder erscheinen jetzt im Payload, die zuvor weggelassen wurden.

Webhook-Payloads aus zwei Anbietern oder Versionen vergleichen

Stripe-Webhook V1 und V2 desselben Event-Typs sehen fast identisch aus und sind es nicht im Geringsten. Genauso GitHub-Webhook-Event-Payloads über API-Versionen hinweg, und Slack-Event-Subscriptions über Scopes hinweg. Füge ein Beispiel-Payload aus jedem ins Diff-Tool ein, um umbenannte Felder, verschobene verschachtelte Objekte und neue Metadaten-Blöcke zu sehen. Das geht schneller, als beide Anbieter-Doku-Seiten nebeneinander zu lesen, vor allem wenn die Doku darüber hinweggeht, welche Felder in der Praxis wirklich auftauchen.

Den Klassiker "läuft auf staging, kaputt auf prod" debuggen

Der klassische Deploy-Kopfschmerz. Dieselbe Client-Anfrage gibt aus Staging und Produktion subtil unterschiedliches JSON zurück. Beides erfassen, beides einfügen, und der Unterschied ist meist eine Config-Flag, ein fehlender Feature-Gate oder eine veraltete gecachte Antwort. Gilt genauso für Multi-Region-Debugging (us-east-1 vs eu-west-1 mit unterschiedlichen Daten), CDN-Cache-Probleme (Cloudflare hat einen alten Body gecacht) und Read-Replica-Lag, bei dem ein Write noch nicht überall propagiert wurde.

Wissenswerte Edge-Cases beim API-Response-Diff

Die Fälle, in denen ein Response-Body-Diff anders urteilt als dein Test-Framework, dein OpenAPI-Tool oder dein Auge. Lohnt sich, vor der Annahme zu überfliegen, der Diff habe einen echten Bug gefunden.

TopicWhat this tool does
Volatile Felder (Timestamps, IDs)created_at, updated_at, request_id, trace_id, server-generierte UUIDs und Pagination-Cursor unterscheiden sich immer zwischen zwei Captures. Mit jq 'del(...)' normalisieren, durch eine Konstante ersetzen, oder vor dem Diff einfach herausbearbeiten. Das Signal, das wirklich zählt, sitzt woanders.
null vs fehlender Schlüssel{"foo": null} und {} sind in JSON unterschiedlich, und viele Serializer (Marshmallow, Jackson, System.Text.Json) haben Einstellungen, die zwischen beidem hin- und herwechseln. Der Diff bringt das ans Licht. Manche Clients behandeln sie als äquivalent, manche nicht; die richtige Antwort ist, was dein Consumer tut, und genau deshalb ist das eine häufige Regressionsquelle nach einem Serializer-Upgrade.
SchlüsselreihenfolgeRFC 8259 definiert JSON-Objekte als unsortiert. Zwei semantisch identische Antworten mit unterschiedlicher Schlüsselreihenfolge erscheinen hier als Diff, weil Textvergleich reihenfolgeabhängig ist. Sortiere beide Seiten vorab mit jq --sort-keys, wenn du reihenfolge-unempfindliches Diffen willst. Achtung beim seltenen Consumer, der auf Reihenfolge angewiesen ist (manche Signatur-Flows, manche Legacy-Parser).
Array-ReihenfolgeArrays in JSON sind sortiert, aber viele APIs liefern Arrays, deren Reihenfolge nicht wirklich vertraglich ist: eine Liste von Berechtigungen, eine Liste von Feature-Flags, eine Liste von Webhook-Subscriptions. Ein Diff markiert ein umsortiertes Array als Änderung, selbst wenn kein Consumer sich darum schert. Wenn Umsortieren in deiner Domäne harmlos ist, sortiere beide Seiten vor dem Diff nach einem stabilen Schlüssel.
JSON.parse-StrengeDer Diff behandelt deine Eingabe als undurchsichtigen Text. Wenn ein Capture ein nachgestelltes Komma, einen unquotierten Schlüssel oder einen Kommentar enthält (in striktem JSON alles unzulässig), wird trotzdem gediffed, sieht aber unnötig laut aus. Lass beide Captures zuerst durch jq . laufen, um neu zu formatieren und ungültige Eingabe abzulehnen. jq nutzt einen strikten RFC-8259-Parser.
Response-Wrapping (data-Envelope vs flach)Viele APIs verpacken Payloads in einem {"data": ...}-Envelope und fügen manchmal meta, links oder included daneben hinzu (JSON:API und Ähnliche). Eine Migration von flach zu verpackt (oder umgekehrt) ist ein Breaking Change, der sofort im Diff auftaucht, aber in einem Schema-Review leicht übersehen wird, weil der zugrundeliegende Datensatz gleich aussieht.
Pagination-Cursor-ÄnderungenCursor-basierte Paginierung nutzt undurchsichtige Tokens (next_cursor, after, page_token), die so designt sind, dass sie sich bei jedem Aufruf ändern. Sie tauchen immer als Diff auf. Vor dem Vergleich entfernen oder nur den Inhalt des data-Arrays vergleichen und den Pagination-Block komplett ignorieren.
Fehler-Response-FormateFehler-Bodys sind der Wilde Westen. Manche APIs liefern ein flaches {"error": "..."}, manche RFC 7807 Problem Details mit type, title, status, detail, instance, und manche eine herstellerspezifische Form. Eine Migration auf RFC 7807 von einer eigenen Form erzeugt einen großen Diff, der überwiegend eine Verbesserung ist; eine Migration in die andere Richtung ist eine Regression, die man früh fangen sollte.

API-Response-Diff: häufige Fragen

Worin unterscheidet sich das vom eingebauten Diff in Postman?

Postman hat eine Response-Vergleichsansicht im Collection Runner und ein Visualize-Feature für einzelne Antworten. Beides ist gut, wenn du in Postman lebst und deine Antworten schon als Postman-Verlaufseinträge gespeichert sind. Dieses Tool ist anbieter-agnostisch. Du kannst aus Postman, Insomnia, curl, httpie, einem CI-Log, einem Stack-Overflow-Snippet oder der Slack-Nachricht eines Kollegen einfügen. Kein Account, kein Workspace, kein Sync. Für einmalige Vergleiche über Tools hinweg ist das schneller. Für team-geteilte API-Tests innerhalb einer einzelnen Plattform ist das eigene Postman-Feature in Ordnung.

Wie gehe ich mit volatilen Feldern wie Timestamps und Request-IDs um?

Der pragmatische Schritt ist, vor dem Diff zu normalisieren. Beide Pastes in den Feldern öffnen und die volatilen Felder direkt herausbearbeiten: Timestamps durch eine konstante Zeichenkette ersetzen, request_id- und trace_id-Werte entfernen, Pagination-Cursor löschen, die sich bei jedem Aufruf ändern. Der Diff hebt nur die verbleibenden Unterschiede hervor, und die sind die, auf die es ankommt. Für wiederholte Vergleiche desselben Endpoints kannst du die Antwort vor dem Einfügen auch durch jq mit einem Delete-Filter (jq 'del(.meta.request_id)') leiten.

Worin unterscheidet sich das von einem OpenAPI-Schema-Diff?

Schema-Diff vergleicht Verträge: Es sagt dir, dass POST /orders ein optionales Feld discount_code hinzubekommen hat oder dass das Enum status einen neuen Wert bekommen hat. OpenAPI-bewusste Tools wie oasdiff oder Spectral können das gut. Dieses Tool vergleicht echte Response-Bodys. Beide ergänzen sich. Schema-Diff fängt Vertragsänderungen ab; Response-Diff fängt den Drift zwischen Vertrag und Realität ab, und genau dort verstecken sich Serialisierungs-Bugs, Umgebungs-Diskrepanzen und veraltete Fixtures.

Verkraftet es große Antworten?

Praktisch ja, bis zu einigen Tausend Zeilen formatiertem JSON pro Seite. Darüber hinaus wird der zeichenbasierte Diff mit semantischer Bereinigung langsam, weil er im Browser läuft, nicht auf einem Server. Für sehr große Payloads (denk an einen paginierten Dump von 10.000 Datensätzen) ist es richtig, die Antwort in kleinere Stücke pro Datensatz oder pro Top-Level-Key zu schneiden und jedes Stück separat zu diffen. Oder einen strukturellen Diff auf der Kommandozeile mit jd oder diff <(jq . a.json) <(jq . b.json) für reine Geschwindigkeit fahren.

Funktioniert es für XML- oder SOAP-Antworten?

Direkt nicht. Diese Seite ist auf JSON abgestimmt, das die meisten modernen REST- und Webhook-Payloads nutzen. Wenn du XML, SOAP-Envelopes, RSS oder POM-artige Konfiguration diffen musst, ist unser compare-xml-Tool die richtige Anlaufstelle; es behandelt Einrückung und Namespace-Formatierung korrekt. Für rohe Response-Bodys, die Header und Body mischen, oder für Plain-Text-APIs (manche Legacy-Systeme geben weiterhin text/plain zurück), erledigt compare-text den Job, ohne eine Struktur erzwingen zu wollen.

Bleibt die Schlüsselreihenfolge erhalten oder wird sie sortiert?

Sie bleibt erhalten, so wie du sie einfügst. JSON-Objekte sind formal unsortiert laut RFC 8259, also erscheinen zwei semantisch identische Antworten mit Schlüsseln in unterschiedlicher Reihenfolge in diesem Tool als Diff. Wenn du die Reihenfolge ignorieren willst, normalisiere beide Seiten erst durch jq --sort-keys oder Vergleichbares. Die meisten Clients hängen nicht von der Schlüsselreihenfolge ab, also ist sortierte-Schlüssel-Normalisierung ein sicherer Standard für Response-Vergleiche; einige Legacy-Consumer (alte XML-zu-JSON-Brücken, bestimmte digitale Signatur-Flows) sind auf Reihenfolge angewiesen.

Datenschutz und warum er für API-Antworten zählt

API-Response-Payloads enthalten regelmäßig Dinge, die nicht nach außen sollen. Kunden-E-Mail-Adressen. Interne Benutzer-IDs. Session-Tokens. Auth-Bearer-Tokens, die versehentlich in einem Body-Feld gelandet sind. Stripe-Customer-IDs. Webhook-Secrets. PII-Felder wie Namen, Adressen und Telefonnummern. Eines davon in einen cloud-gehosteten Diff-Service zu kleben ist selbst schon ein Datenverarbeitungsvorgang und kann je nach Branche deine SOC-2-Kontrollen, GDPR-Auftragsverarbeitungsverträge oder HIPAA Business Associate Agreements verletzen. Dieses Tool läuft komplett in deinem Browser. Nichts wird hochgeladen, geloggt oder an einen Drittdienst gesendet. Diff, Hervorhebung und Rendering laufen alle auf deinem Rechner. Die Behauptung lässt sich leicht prüfen: DevTools öffnen, Network-Tab wählen, beide Antworten einfügen und beobachten. Beim Vergleich gibt es keine ausgehenden Requests. Für umfassendere Hinweise zu API-Design und -Sicherheit sind die API-Design-Best-Practices von Microsoft eine solide Referenz.