Every developer has experienced the frustration of an API that returns unexpected data. The endpoint returns a 200 status code but the response body is empty. The JSON parses successfully but a critical field is null when it shouldn't be. The API works perfectly in Postman but fails in your application. The response starts with a BOM character that silently breaks your JSON parser. These issues can consume hours of debugging time if you don't have a systematic approach to diagnosing them.
JSON API debugging is fundamentally different from traditional code debugging. The error might be in your request (wrong headers, missing authentication, malformed request body), in the network layer (CORS blocking, SSL certificate issues, proxy interference), in the server (500 errors, rate limiting, incorrect serialization), or in your client-side parsing (wrong assumptions about data structure, type mismatches, encoding issues). Effective debugging requires systematically eliminating each potential failure point.
This guide provides a complete, step-by-step debugging methodology that covers every common API failure mode. We'll walk through the tools, techniques, and patterns that professional developers use to diagnose JSON API issues quickly and reliably. Each section includes practical code examples, real-world error scenarios, and solutions you can apply immediately.
Format & Inspect API Responses
Paste any API response into our JSON Formatter for instant syntax validation, tree view visualization, and error highlighting.
Open JSON Formatter →Step 1: Inspect the Raw Response
Before debugging your code, always examine the raw API response. Many issues become immediately apparent when you look at the actual data the API returned rather than what your code tried to do with it.
Using browser DevTools: Open the Network tab (F12), trigger the API call, click on the request in the list, and examine the Response and Headers tabs. Check three things: the HTTP status code, the Content-Type header (should be application/json), and the raw response body.
Using curl: Run the equivalent request from the command line with verbose output to see the complete request/response cycle including headers:
# Verbose output shows headers + body
curl -v https://api.example.com/users/1
# Pretty-print JSON response
curl -s https://api.example.com/users/1 | python -m json.tool
# Include response headers in output
curl -i https://api.example.com/users/1Step 2: Validate the JSON Syntax
If the response looks like JSON but your parser rejects it, the issue is almost always a syntax error in the response. Copy the raw response text and paste it into our JSON Formatter — it will immediately highlight any syntax errors with line numbers and specific error descriptions.
The most common malformed JSON scenarios include:
| Symptom | Cause | Fix |
|---|---|---|
| SyntaxError at position 0 | Response is HTML, not JSON (error page or login redirect) | Check URL, authentication, Content-Type header |
| Unexpected token at start | BOM (Byte Order Mark) character \uFEFF |
Strip BOM: text.replace(/^\uFEFF/, '') |
| Unexpected token after valid JSON | Multiple JSON objects concatenated (streaming) | Parse each line separately (NDJSON) |
| Unexpected end of JSON | Truncated response (timeout, size limit) | Increase timeout, check server logs |
| Trailing comma errors | Server serialization bug | Fix server-side; or strip trailing commas client-side |
Step 3: Check HTTP Status Codes
The HTTP status code tells you whether the request succeeded before you even look at the response body. Many developers only check for status 200, but understanding the full range of codes is essential for proper API handling:
| Status Code | Meaning | Response Body | Action Required |
|---|---|---|---|
| 200 OK | Success — data returned | Expected JSON data | Parse normally |
| 201 Created | Resource created | New resource data + Location header | Parse + follow Location |
| 204 No Content | Success — no data | Empty (no body) | Don't try to parse |
| 400 Bad Request | Invalid request | Error details | Fix request body/params |
| 401 Unauthorized | Not authenticated | Auth error message | Add/fix auth token |
| 403 Forbidden | Not authorized | Permission error | Check API key/permissions |
| 404 Not Found | Resource doesn't exist | May be HTML error page | Verify URL and resource ID |
| 429 Too Many Requests | Rate limited | Rate limit info + Retry-After header | Implement backoff/retry |
| 500 Internal Error | Server crashed | May be HTML stack trace | Check server logs, report bug |
Step 4: Handle Nested Data Safely
A common source of runtime errors is accessing deeply nested JSON properties without checking that intermediate objects exist. When the API returns an unexpected structure — perhaps a field is null, an array is empty, or a nested object is missing entirely — your code throws a TypeError: "Cannot read property 'x' of undefined."
// ❌ Unsafe — throws if any level is null/undefined
const city = response.data.users[0].address.city;
// ✅ Safe — returns undefined if any level is missing
const city = response?.data?.users?.[0]?.address?.city;
// ✅ Safe with default — returns "Unknown" if missing
const city = response?.data?.users?.[0]?.address?.city ?? "Unknown";
// ✅ Validation before access
if (response?.data?.users?.length > 0) {
const user = response.data.users[0];
console.log(user.name, user.address?.city);
}Step 5: Debug CORS Issues
Cross-Origin Resource Sharing (CORS) errors are among the most confusing API issues because the API works perfectly in Postman and curl but fails in the browser. CORS is a browser security mechanism that blocks API requests from a different origin (domain, protocol, or port) unless the server explicitly allows it.
CORS errors appear in the browser console as: "Access to fetch at 'https://api.example.com/data' from origin 'https://mysite.com' has been blocked by CORS policy." The key thing to understand is that CORS is enforced by the browser, not the server. The API actually received and processed your request — the browser simply blocks your JavaScript from reading the response.
The fix is always server-side: The API server must include Access-Control-Allow-Origin headers in its response specifying which origins are allowed to call it. If you don't control the API server, you'll need to proxy the request through your own backend server, which isn't subject to browser CORS restrictions.
Step 6: Debug Common Data Parsing Issues
Even when the JSON is perfectly valid and the status code is 200, the data itself might cause your application logic to fail. These are semantic errors, not syntax errors.
| Issue | Symptom | Solution |
|---|---|---|
| Dates as strings | Date fields are ISO strings, not Date objects | Parse with new Date(str) after JSON.parse |
| Large numbers | IDs over 2^53 lose precision in JavaScript | Use BigInt or request stringified IDs from the API |
| Unicode encoding | Characters render as \u00e9 or garbled |
Ensure UTF-8 encoding, set charset=utf-8 in headers |
| Null vs missing | {"field": null} vs field entirely absent |
Check with "field" in obj vs obj.field != null |
| String numbers | "price": "29.99" instead of 29.99 |
Explicitly cast: parseFloat(obj.price) |
Step 7: Master Network Interception (Proxies)
Browser DevTools are great for frontend web apps, but what if you are debugging a mobile app, a backend Node.js microservice, or a third-party script you don't control? You need a Man-in-the-Middle (MITM) proxy to intercept and inspect the raw HTTP traffic.
Tools like Charles Proxy, Fiddler, or Proxyman act as a middleman between your client and the server. By configuring your system or device to route traffic through the proxy, and installing the proxy's SSL certificate, you can decrypt, view, and even modify HTTPS traffic in real-time. This is the ultimate technique for proving whether a bug lies in the client SDK generating the request or the server generating the response.
Step 8: Reverse Engineer Undocumented APIs
Sometimes you need to integrate with an API that has terrible (or nonexistent) documentation. Debugging in this scenario requires a forensic approach:
- Open the official web app: If the service has a web dashboard, open it with the Network tab open.
- Perform the action: Click the button or load the page that triggers the data you want.
- Copy as cURL: Right-click the relevant XHR/Fetch request in DevTools and select "Copy as cURL". This copies the exact request, including the necessary authentication cookies, CSRF tokens, and headers.
- Replay and isolate: Paste the cURL command into your terminal to verify it works. Then, systematically remove headers one by one to determine exactly which authentication tokens are strictly required.
Step 9: Debugging Pagination and Large Datasets
APIs rarely return a million records in a single JSON array. Instead, they use pagination. A common bug occurs because developers test against an endpoint with 5 records, but in production, the 100th record triggers a malformed response, or the pagination cursor logic is flawed.
Cursor vs. Offset Bugs: If the API uses offset and limit, new records inserted during your pagination loop will shift the offsets, causing you to process duplicate records or skip them entirely. If the API uses cursor-based pagination (e.g., passing a next_cursor token), debugging requires painstakingly tracking the exact token value returned in response N and ensuring it is perfectly injected into request N+1.
Step 10: Asynchronous and Webhook Debugging
Not all APIs return data immediately. Many modern systems use asynchronous patterns: you send a POST request, receive a 202 Accepted, and the server later sends a POST request back to your Webhook URL with the final JSON payload.
Debugging a webhook you are writing code to receive is notoriously difficult because it happens in the background. Do not attempt to debug this solely by reading your server's obscure log files. Instead:
- Use Webhook.site to instantly generate a public URL. Point the third-party API to this URL to inspect the exact JSON payload, headers, and structure they are sending in real-time.
- Use Ngrok to tunnel public internet traffic directly to your
localhostserver. This allows you to set breakpoints in your IDE and step through the incoming JSON webhook exactly as if you were running the request locally.
Step 11: The API Versioning Trap
A sudden, inexplicable bug where JSON parsing suddenly fails with "missing required field" in a system that has been stable for months is frequently caused by undeclared API versioning.
The provider updated their backend (e.g., renaming first_name to firstName or splitting address into an object). If your client requests don't explicitly pin an API version (either via URL like /v1/users, or via an Accept-Version header), you are silently opted-in to breaking schema changes. Always verify exactly which version of the JSON schema the server is currently returning compared to what your parser expects.
Essential Debugging Tools
| Tool | Type | Best For | Free? |
|---|---|---|---|
| DominateTools JSON Formatter | Web tool | Quick validation, syntax errors, tree view | Yes |
| Postman | Desktop / Web app | Full request builder, collections, testing | Free tier |
| curl | CLI | Quick request testing, scripts | Yes |
| HTTPie | CLI | Human-friendly curl alternative | Yes (CLI) |
| Browser DevTools | Browser built-in | Live request inspection, CORS debugging | Yes |
| jq | CLI | Command-line JSON processing and filtering | Yes |
Validate API Responses Instantly
Paste raw JSON into our formatter — instant syntax validation, error highlighting, and tree view navigation.
Open JSON Formatter →Frequently Asked Questions
How do I debug a JSON API response?
Why does JSON.parse throw an error?
How do I handle nested JSON data?
?.) to safely access nested properties: data?.users?.[0]?.address?.city. This returns undefined instead of throwing errors on missing intermediate properties. Add nullish coalescing (??) for defaults.
What is the difference between 200 and 201 status codes?
Location header pointing to the new resource.
How do I test API endpoints without writing code?
Related Resources
- JSON to CSV Converter — Try it free on DominateTools
- JSON Syntax Guide — Complete JSON reference
- JSON vs XML vs YAML — Format comparison
- JSON Schema Validation — Enforce data structure rules
- JSON Best Practices — Design and performance tips
- Free JSON Formatter — Validate and debug JSON