# HTTP 200 OK (but something is still wrong)

**Code:** `200` · **Category:** HTTP · **Seen on:** JavaScript, PHP, REST API

The request succeeded at the HTTP level — yet the page is blank, the data is wrong, or an error is hidden inside the response body.

## Meaning

200 only means the server returned a response without an HTTP-level error. Plenty of real failures arrive as 200: APIs that wrap errors in the JSON body (`{"success": false}`), GraphQL (which returns 200 with an `errors` array), SPA fallbacks that serve index.html for every URL, cached stale responses, and login pages served with 200 after a silent redirect.

## Common causes

- API reports the error in the body with status 200 (`{"ok": false, "error": ...}`)
- GraphQL errors — always in the `errors` array, often with HTTP 200
- SPA/rewrite fallback returns index.html (200) for a wrong API path
- Redirect to a login page followed silently by fetch → final 200 with HTML
- Stale content served from browser/CDN cache
- Soft 404: “not found” page served with 200 (bad for SEO)

## Quick fix

1. Inspect the response body and Content-Type, not just the status
2. Check `res.redirected` / `res.url` in fetch
3. Return proper 4xx/5xx statuses from your own APIs
4. For SEO, make “not found” pages return a real 404

## Detailed fix by platform

### JavaScript

1. Check status, type and body-level errors:

```javascript
const res = await fetch('/api/profile');
const type = res.headers.get('content-type') || '';
if (!type.includes('application/json')) throw new Error(`Expected JSON, got ${type} from ${res.url}`);
const body = await res.json();
if (body.errors || body.success === false) throw new Error(JSON.stringify(body.errors ?? body.error));
```


### PHP

1. Send the real status: `http_response_code(404); echo json_encode(['error' => 'not_found']);`

## How to diagnose

1. **Body** — What does the response body actually contain?
2. **Content-Type** — JSON or HTML?
3. **Final URL** — Did a redirect land somewhere unexpected?
4. **Cache** — Is this a cached copy (Age / X-Cache headers)?

---
Source: [WhatIsMyError](https://whatismyerror.com/errors/http/200-ok)
