Skip to content

HTTP status code · Success (2xx)

201 Created

201 Created means the request succeeded and created one or more new resources, typically after a POST to a collection or a PUT to a new URL. The response should carry a Location header with the new resource's URL; without it, the request URL itself is taken as the created resource.

Facts about this status code
Class2xx, Success
Defined inRFC 9110 §15.3.2
Cacheable by defaultOnly with explicit Cache-Control or Expires
Safe to retryDo not repeat a POST that got 201, or you create a duplicate
Relevant headers
  • Location: URL of the new resource; without it the request URL is taken as the new resource
  • ETag: validator of the newly created representation, handy for later conditional updates

What 201 means

RFC 9110, section 15.3.2, identifies the primary new resource by the Location header or, when Location is absent, by the target URI. The body typically describes and links to what was created, and any ETag you send is the validator of the new representation.

For PUT the rule is strict: section 9.3.4 says that if the PUT created a representation that did not exist, the server MUST answer 201; if it replaced an existing one, it answers 200 or 204. If the resource will only exist after background work finishes, 201 is premature and 202 Accepted is the honest answer.

When to use it

  • POST /orders that creates an order with an ID the server chose: 201 plus Location: /orders/1234.
  • PUT /files/report.pdf that uploads a file which did not exist before.
  • Return the created object in the body as well, so the client does not need a second GET to learn server-generated fields such as id or createdAt.

Common causes

If you run the server

  • A retried POST (double click, mobile network timeout) returns 201 twice and creates two orders, because POST is not idempotent.
  • The client cannot find what it created: Location is missing, or it is relative and the client resolves it against the wrong base URL.

How to fix it

If you run the server

  • Accept an Idempotency-Key request header on create endpoints and return the original 201 when the same key comes back.
  • Always send Location; a relative value like /orders/1234 is valid and is resolved against the request URL.

How to send 201

Express (Node.js)
app.post('/reports', (req, res) => {
  res.set('Location', '/reports/42');
  res.status(201).json({ id: '42', title: 'Q3 revenue' });
});
Next.js App Router route handler
// app/reports/route.ts
export async function POST() {
  return Response.json(
    { id: '42', title: 'Q3 revenue' },
    { status: 201, headers: { 'Location': '/reports/42' } }
  );
}
Go net/http
mux.HandleFunc("POST /reports", func(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Location", "/reports/42")
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusCreated) // 201
	w.Write([]byte(`{"id":"42","title":"Q3 revenue"}`))
})
Python FastAPI
from fastapi import FastAPI
from fastapi.responses import JSONResponse

app = FastAPI()

@app.post("/reports")
def create_report():
    return JSONResponse(status_code=201, content={"id": "42", "title": "Q3 revenue"}, headers={"Location": "/reports/42"})

Commonly confused with

201 vs 200
200 on a POST reports that an action succeeded; 201 specifically says something new now exists at a URL.
201 vs 202
202 Accepted means creation was queued and may still fail; 201 means the resource already exists when the response is sent.
201 vs 303
HTML forms usually answer a successful POST with 303 See Other to a result page (post/redirect/get); APIs answer 201.

Frequently asked questions

Is the Location header required on a 201?
Not strictly. RFC 9110 says the new resource is identified by Location or, if there is none, by the request URL. For a POST to a collection the new URL differs from the request URL, so in practice you should always send it.
Should a 201 response include a body?
It may and usually should. The spec says the content typically describes and links to the created resources; most APIs return the full created object so clients get server-generated fields immediately.
Which status should a PUT return when it creates a resource?
201 Created. RFC 9110, section 9.3.4, requires 201 when a PUT creates a representation that did not exist, and 200 or 204 when it replaces one that did.
How do I stop duplicate records when a client retries a POST?
Have the client send a unique Idempotency-Key header and store it with the result. When the same key arrives again, return the stored 201 response instead of creating another record.

Last reviewed by Arielton Oberek.