# HTTP 200 OK: What It Means and When to Use It

> 200 OK means the request succeeded and the response carries the result. What a 200 should contain, and when 201, 204 or 206 is the better answer for your API.

Source: https://howhttpworks.com/status-codes/200
Last reviewed: 2026-10-05

> **TL;DR:** 200 OK means your request succeeded. The server processed it and is returning the requested data.

200 OK is the most common HTTP status code. It means everything worked—the server received your request, understood it, processed it successfully, and is sending back the result.

## What is 200 OK?

When a server returns 200 OK, it's saying "your request succeeded, here's what you asked for":

```http
GET /api/users/123 HTTP/1.1
Host: api.example.com
```

Response:

```http
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 89

{
  "id": 123,
  "name": "Alice Johnson",
  "email": "alice@example.com"
}
```

## When Servers Return 200

### GET Request - Resource Retrieved

```http
GET /products/456 HTTP/1.1
Host: shop.example.com

HTTP/1.1 200 OK
Content-Type: application/json

{
  "id": 456,
  "name": "Wireless Headphones",
  "price": 79.99
}
```

### POST Request - Action Completed

```http
POST /api/login HTTP/1.1
Content-Type: application/json

{"email": "user@example.com", "password": "..."}

HTTP/1.1 200 OK
Content-Type: application/json

{
  "token": "eyJhbGciOiJIUzI1NiIs...",
  "user": {"id": 123, "name": "User"}
}
```

### PUT Request - Resource Updated

```http
PUT /api/users/123 HTTP/1.1
Content-Type: application/json

{"name": "Alice Smith"}

HTTP/1.1 200 OK
Content-Type: application/json

{
  "id": 123,
  "name": "Alice Smith",
  "updatedAt": "2026-01-19T10:30:00Z"
}
```

### DELETE Request - Resource Removed

```http
DELETE /api/posts/789 HTTP/1.1

HTTP/1.1 200 OK
Content-Type: application/json

{
  "message": "Post deleted successfully",
  "deletedId": 789
}
```

## Response Body Content

The response body varies by request type:

### HTML Page

```http
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8

<!DOCTYPE html>
<html>
<head><title>Welcome</title></head>
<body><h1>Hello, World!</h1></body>
</html>
```

### JSON Data

```http
HTTP/1.1 200 OK
Content-Type: application/json

{
  "users": [
    {"id": 1, "name": "Alice"},
    {"id": 2, "name": "Bob"}
  ],
  "total": 2
}
```

### Image File

```http
HTTP/1.1 200 OK
Content-Type: image/png
Content-Length: 12345

[binary PNG data]
```

### Empty Array (Valid 200)

```http
HTTP/1.1 200 OK
Content-Type: application/json

{
  "results": [],
  "total": 0
}
```

## Common Response Headers

| Header           | Purpose          | Example                         |
| ---------------- | ---------------- | ------------------------------- |
| `Content-Type`   | Body format      | `application/json`              |
| `Content-Length` | Body size        | `1234`                          |
| `Cache-Control`  | Caching rules    | `max-age=3600`                  |
| `ETag`           | Resource version | `"abc123"`                      |
| `Last-Modified`  | Last change      | `Sat, 18 Jan 2026 10:00:00 GMT` |
| `Set-Cookie`     | Set cookies      | `session=xyz; HttpOnly`         |

## 200 OK vs Other Success Codes

| Code    | Name       | When to Use                        |
| ------- | ---------- | ---------------------------------- |
| **200** | OK         | General success with response body |
| **201** | Created    | New resource created (POST)        |
| **202** | Accepted   | Request queued for processing      |
| **204** | No Content | Success but no body to return      |

### Choosing the Right Code

```http
# GET request - use 200
GET /users/123 → 200 OK with user data

# POST creating resource - use 201
POST /users → 201 Created with new user + Location header

# DELETE with no response body - use 204
DELETE /users/123 → 204 No Content

# POST triggering async job - use 202
POST /reports/generate → 202 Accepted
```

## Getting 200 OK right

### Do Return Useful Data

```http
HTTP/1.1 200 OK
Content-Type: application/json

{
  "success": true,
  "data": {
    "id": 123,
    "name": "Alice"
  },
  "meta": {
    "requestId": "req-abc-123",
    "timestamp": "2026-01-19T10:30:00Z"
  }
}
```

### Don't Return 200 for Errors

```http
# ❌ Bad: 200 with error in body
HTTP/1.1 200 OK
{"error": "User not found"}

# ✅ Good: Proper error status
HTTP/1.1 404 Not Found
{"error": "User not found"}
```

### Include Appropriate Headers

```http
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: max-age=300
ETag: "v1-abc123"
X-Request-ID: req-xyz-789

{"data": "..."}
```

## JavaScript Handling

### Fetch API

```javascript
const response = await fetch('/api/users/123')

if (response.ok) {
  // true for 200-299
  const user = await response.json()
  console.log('User:', user)
} else {
  console.error('Request failed:', response.status)
}
```

### Checking Specifically for 200

```javascript
const response = await fetch('/api/data')

if (response.status === 200) {
  const data = await response.json()
  // Process successful response
}
```

### With Error Handling

```javascript
async function fetchUser(id) {
  const response = await fetch(`/api/users/${id}`)

  if (!response.ok) {
    throw new Error(`HTTP ${response.status}`)
  }

  return response.json()
}

try {
  const user = await fetchUser(123)
  displayUser(user)
} catch (error) {
  showError(error.message)
}
```

## API Response Patterns

### Standard Success Response

```json
{
  "status": "success",
  "data": {
    "id": 123,
    "name": "Alice"
  }
}
```

### Paginated Response

```json
{
  "data": [
    { "id": 1, "name": "Alice" },
    { "id": 2, "name": "Bob" }
  ],
  "pagination": {
    "page": 1,
    "perPage": 20,
    "total": 150,
    "totalPages": 8
  }
}
```

### Response with Metadata

```json
{
  "data": { "id": 123 },
  "meta": {
    "requestId": "req-abc",
    "processingTime": "45ms",
    "apiVersion": "v1"
  }
}
```

## Try It Yourself

See a 200 OK response in our [request builder](https://howhttpworks.com/tools/playground?preset=get-one):

1. Select **GET** method
2. Set path to `/posts/1`
3. Click **Send** and observe the 200 response with post data

## Try it with curl

```bash
curl -i https://api.example.com/items/42
```

Example output (illustrative, not captured from a real server):

```http
HTTP/2 200
content-type: application/json
content-length: 41

{"id":42,"name":"Widget","price":9.99}
```

`-i` prints the status line and headers before the body. Add `-o /dev/null -w '%{http_code}\n'` to print only the status code.

## Related Status Codes

- [201 Created](https://howhttpworks.com/status-codes/201) - New resource created
- [204 No Content](https://howhttpworks.com/status-codes/204) - Success with no body
- [304 Not Modified](https://howhttpworks.com/status-codes/304) - Cached version is current
- [400 Bad Request](https://howhttpworks.com/status-codes/400) - Request was invalid
- [500 Internal Server Error](https://howhttpworks.com/status-codes/500) - Server failed

## Related Concepts

- [HTTP Methods](https://howhttpworks.com/methods/get) - Request types
- [Content-Type](https://howhttpworks.com/headers/content-type) - Response format
- [Caching](https://howhttpworks.com/headers/cache-control) - Storing responses
- [206 Partial Content](https://howhttpworks.com/status-codes/206) - Only the requested byte range

See also the comparison [200 vs 201 vs 204](https://howhttpworks.com/compare/200-vs-201-vs-204): choosing the right success code for create, read, update and delete.
