- Home
- HTTP Status Codes
- HTTP 200 OK: Success Response Explained
Status Code
HTTP 200 OK: Success Response Explained
Learn what HTTP 200 OK means, when servers return it, and how to handle successful responses in your applications.
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”:
GET /api/users/123 HTTP/1.1
Host: api.example.com
```text
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
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
}
```text
### 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
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"
}
```text
### 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/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>
```text
### 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/1.1 200 OK
Content-Type: image/png
Content-Length: 12345
[binary PNG data]
```text
### 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
# 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
```text
## Best Practices
### 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
# ❌ 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"}
```http
### 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
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)
}
```javascript
### 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
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)
}
```text
## API Response Patterns
### Standard Success Response
```json
{
"status": "success",
"data": {
"id": 123,
"name": "Alice"
}
}
Paginated Response
{
"data": [
{ "id": 1, "name": "Alice" },
{ "id": 2, "name": "Bob" }
],
"pagination": {
"page": 1,
"perPage": 20,
"total": 150,
"totalPages": 8
}
}
```text
### 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:
- Select GET method
- Set path to
/posts/1 - Click Send and observe the 200 response with post data
Related Status Codes
- 201 Created - New resource created
- 204 No Content - Success with no body
- 304 Not Modified - Cached version is current
- 400 Bad Request - Request was invalid
- 500 Internal Server Error - Server failed
Related Concepts
- HTTP Methods - Request types
- Content-Type - Response format
- Caching - Storing responses
In Practice
Express.js
// GET — return resource
app.get('/api/users/:id', async (req, res) => {
const user = await db.users.findById(req.params.id)
if (!user) return res.status(404).json({ error: 'Not found' })
res.status(200).json(user) // or just res.json(user)
})
// POST — action succeeded, return result
app.post('/api/search', async (req, res) => {
const results = await search(req.body.query)
res.json({ results, total: results.length })
// 200 is default — no need to set explicitly
})Next.js App Router
// app/api/users/[id]/route.ts
export async function GET(
_req: Request,
{ params }: { params: { id: string } }
) {
const user = await db.users.findById(params.id)
if (!user) return new Response(null, { status: 404 })
// Response.json() defaults to 200
return Response.json(user)
}Django
from django.http import JsonResponse
def user_detail(request, user_id):
try:
user = User.objects.get(pk=user_id)
# JsonResponse defaults to status=200
return JsonResponse(user.to_dict())
except User.DoesNotExist:
return JsonResponse({'error': 'Not found'}, status=404)Frequently Asked Questions
What does HTTP 200 OK mean?
HTTP 200 OK means the request was successful. The server understood the request, processed it correctly, and is returning the requested data. It is the standard success response for GET, POST, PUT, and other HTTP methods.
When should a server return 200 OK?
Return 200 OK when a request succeeds and you have content to return. For GET requests, return the requested resource. For POST/PUT, return the created or updated resource. Use 201 Created for new resources and 204 No Content when there is nothing to return.
What is the difference between 200 OK and 201 Created?
200 OK is a general success response. 201 Created specifically indicates a new resource was created, typically from a POST request. 201 should include a Location header pointing to the new resource.
Can a 200 response have an empty body?
Yes, but 204 No Content is more appropriate for successful requests with no response body. Use 200 OK when you have content to return, even if it is just a success message or empty array.
Does 200 OK mean there were no errors?
Not always. Some APIs return 200 OK with error details in the body. This is considered bad practice. Proper APIs use appropriate error status codes (4xx, 5xx) for errors and reserve 200 for actual success.