HTTP status codes for WordPress sites tell browsers, search engines, APIs, proxies and monitoring systems what actually happened when they requested a URL.
They are easy to overlook because visitors normally see the page rather than the response headers behind it.
Yet the difference between:
200 OK
301 Moved Permanently
404 Not Found
503 Service Unavailable
can completely change how a browser, crawler or integration interprets the same visible page.
A custom “Page not found” design returning 200 OK is still technically a successful response.
A maintenance page returning 200 OK can look like ordinary site content to automated systems.
A deleted URL returning 301 tells clients to look somewhere else permanently, while 410 Gone explicitly says the resource has been intentionally removed.
And an apparent WordPress error returning 502 Bad Gateway may not have been generated by WordPress at all. It may come from Nginx, a reverse proxy, CDN or hosting infrastructure that could not obtain a valid response from PHP or another upstream service.
This guide explains the HTTP status codes WordPress administrators and developers encounter most often, including 200, 201, 204, 206, 301, 302, 303, 304, 307, 308, 400, 401, 403, 404, 405, 409, 410, 413, 416, 422, 429, 500, 502, 503 and 504.
It also explains how WordPress sends status headers, how redirects affect SEO, why soft 404s happen, which errors typically originate outside WordPress and how to inspect the real response instead of guessing from what appears in the browser.
What is an HTTP status code?
When a browser requests:
https://example.com/services/
the server returns an HTTP response.
Conceptually:
Browser
↓
HTTP request
↓
Server / WordPress
↓
HTTP response
├── status code
├── headers
└── body
The status code is a three-digit number describing the outcome of that request.
The current HTTP Semantics specification defines the standard meaning of the major HTTP response codes.
HTTP statuses are grouped into five classes
The MDN HTTP status reference groups responses into:
1xx
Informational
2xx
Successful
3xx
Redirection
4xx
Client errors
5xx
Server errors
The first digit gives you the broad meaning
For most WordPress debugging, this immediately narrows the problem.
2xx
The request basically worked.
3xx
The client needs to go somewhere else
or use cached information.
4xx
The requested resource or request
has a client-side/access problem.
5xx
The server failed to complete
a valid request.
The visible page and HTTP status are separate things
This is the single most important concept in this guide.
You can render:
<h1>Page not found</h1>
while sending:
HTTP/1.1 200 OK
That creates an error page visually but a successful response technically.
The reverse is also possible
You could render a beautifully designed maintenance page while correctly sending:
HTTP/1.1 503 Service Unavailable
The browser displays the HTML, while automated clients understand that the current outage is temporary.
Status code and response body solve different problems
STATUS CODE
Communicates machine-readable
request outcome
RESPONSE BODY
Communicates information
to the visitor or application
WordPress can set HTTP status headers itself
WordPress provides the official status_header() function.
For example:
status_header( 404 );
can send a response header such as:
HTTP/1.1 404 Not Found
status_header() does not magically create the rest of the response
Setting:
status_header( 404 );
does not automatically:
- load your theme’s 404 template;
- stop PHP execution;
- redirect the user;
- remove already generated output;
- create a useful error page.
It sets the HTTP status header.
WordPress knows descriptions for many HTTP codes
The Core get_status_header_desc() function maps known codes to descriptions such as:
200 → OK
301 → Moved Permanently
302 → Found
404 → Not Found
410 → Gone
429 → Too Many Requests
500 → Internal Server Error
502 → Bad Gateway
503 → Service Unavailable
504 → Gateway Timeout
WordPress may not be the component sending the final status
A WordPress request can pass through several layers:
Visitor
↓
CDN
↓
WAF
↓
Load balancer
↓
Reverse proxy
↓
Web server
↓
PHP-FPM
↓
WordPress
↓
Database
Any relevant layer can fail before WordPress finishes the request.
This is especially important for 5xx errors
A:
500
may originate inside PHP or WordPress.
A:
502
is often generated by a gateway or proxy.
A:
504
usually means a gateway waited too long for an upstream service.
Seeing “WordPress is down” in a browser therefore does not automatically mean WordPress produced the error.
200 OK
200 OK is the normal successful response for an ordinary webpage.
For example:
GET /services/
HTTP/1.1 200 OK
This normally means the request succeeded and the server is returning the requested representation.
A normal indexable WordPress page generally returns 200
Examples include:
- homepage;
- published post;
- published page;
- public custom post type;
- valid taxonomy archive.
200 does not prove the page is actually healthy
The HTML could still contain:
Database connection failed
Product does not exist
Page not found
Temporary error
while the HTTP response remains:
200 OK
This creates soft 404 problems
Google describes a soft 404 as a URL that appears to contain an error or missing-content message while returning a successful 200 status.
The official Google Search crawling error documentation explicitly recommends returning a real 404 or 410 when content no longer exists and has no suitable replacement.
A custom 404 page should still return 404
Good:
HTTP/1.1 404 Not Found
<h1>We couldn't find that page</h1>
<a href="/">Return home</a>
Bad:
HTTP/1.1 200 OK
<h1>404 – Page not found</h1>
201 Created
201 Created means a request successfully created a new resource.
This is more relevant to APIs than ordinary frontend WordPress page views.
Conceptually:
POST /wp-json/example/v1/items
→ create resource
HTTP/1.1 201 Created
REST APIs can use 201 after successful creation
For an API consumer, this is more descriptive than returning:
200 OK
for every successful operation regardless of what actually happened.
204 No Content
204 No Content means the request succeeded but there is no response body to return.
It is common in APIs and programmatic actions.
For example:
DELETE resource
↓
successful
↓
nothing else to return
↓
204 No Content
Do not return a normal HTML document with 204
The meaning of 204 is specifically that the response has no content body.
206 Partial Content
206 Partial Content is useful when a client requests only part of a file using an HTTP Range request.
This is particularly relevant to:
- video;
- audio;
- large downloads;
- seeking within media.
A browser may request only a byte range
For example:
Range: bytes=1000000-1999999
The server can respond:
206 Partial Content
and return only the requested portion.
WordPress may not handle the actual file response
Files inside:
wp-content/uploads/
are often served directly by:
- Nginx;
- Apache;
- CDN;
- object storage.
So a media-related HTTP status may originate outside PHP and WordPress Core entirely.
301 Moved Permanently
301 Moved Permanently means the requested resource has permanently moved to another URL.
The response normally includes:
Location:
https://example.com/new-url/
Use 301 for permanent URL changes
Typical WordPress examples include:
/old-service/
→ /services/
/old-post-slug/
→ /new-post-slug/
http://example.com/
→ https://example.com/
301 matters during WordPress migrations
If an old indexed URL becomes:
https://example.com/new-location/
a permanent redirect communicates that the new URL is now the canonical destination.
For the deeper decision between permanent, temporary and removed content, see 301 vs. 302 vs. 410: which redirect to use?.
Do not redirect every deleted page to the homepage
Suppose:
/blue-running-shoes/
no longer exists.
If there is a direct replacement:
/running-shoes/blue/
a permanent redirect makes sense.
If no meaningful replacement exists, a:
404
or
410
may be more accurate than:
301 → homepage
302 Found
302 Found is traditionally used for a temporary redirect.
Conceptually:
/campaign/
→ temporarily
/summer-campaign/
The original URL remains conceptually valid
A temporary redirect communicates:
This resource is somewhere else
for now.
rather than:
This resource has permanently moved.
301 and 302 are not interchangeable just because both redirect
If the move is permanent, use a permanent redirect.
If the move is genuinely temporary, use a temporary one.
303 See Other
303 See Other tells the client to retrieve another URL using a GET request.
It is useful in patterns such as:
POST form
↓
process data
↓
303
↓
GET confirmation page
This is known as Post/Redirect/Get
It helps avoid accidentally resubmitting form data when a user refreshes the resulting page.
304 Not Modified
304 Not Modified is a caching response.
It does not mean:
The webpage was not edited in WordPress.
It means the requested representation has not changed relative to the client’s conditional request.
Conditional requests can use validators
For example:
If-None-Match
If-Modified-Since
The server may respond:
304 Not Modified
telling the client it can continue using its cached representation.
304 can reduce transferred bytes
The browser does not need the complete resource body again when the cached version remains valid.
Do not confuse 304 with redirects
Although 304 belongs to the 3xx family, it does not send visitors to a new URL in the way 301 or 302 does.
307 Temporary Redirect
307 Temporary Redirect is a temporary redirect that preserves the HTTP request method.
For example:
POST /old-endpoint/
↓
307
↓
POST /new-endpoint/
This differs from historical 302 behavior
With 307, the client must not convert the original method to:
GET
merely because of the redirect.
308 Permanent Redirect
308 Permanent Redirect is the permanent equivalent of 307.
It communicates:
Permanent destination
+
preserve HTTP method
301 vs. 308
Both indicate a permanent move.
The important technical distinction is method preservation.
301
Permanent redirect
308
Permanent redirect
with explicit method preservation
For normal GET pages, 301 remains extremely common
For API endpoints and other requests where preserving methods and bodies matters, 307 and 308 can be more precise.
WordPress provides redirect functions
WordPress includes:
wp_redirect()
wp_safe_redirect()
for application-level redirects.
wp_safe_redirect() adds validation intended for redirects to allowed hosts.
A WordPress redirect should normally stop execution afterwards
A common pattern is conceptually:
wp_safe_redirect( $url, 301 );
exit;
Sending a Location header does not mean all subsequent PHP should continue executing as though nothing happened.
Redirect Manager centralizes redirect rules
TheOneWP Redirect Manager can manage redirect rules inside WordPress without forcing every migration mapping into server configuration.
Redirects should be monitored after launch
Logs can help identify:
- frequently requested legacy URLs;
- redirect loops;
- incorrect mappings;
- unexpected requests;
- obsolete rules.
See Reading a redirect access log.
Avoid redirect chains
Poor:
/old/
↓ 301
/older-new/
↓ 301
/new/
↓ 301
/final/
Better:
/old/
↓ 301
/final/
Avoid redirect loops
For example:
/a/
→ /b/
/b/
→ /a/
The browser eventually stops following the redirects.
400 Bad Request
400 Bad Request means the server cannot process the request because the request itself is invalid or malformed.
In WordPress this is more common in:
- REST API requests;
- AJAX endpoints;
- custom integrations;
- invalid parameters;
- malformed request bodies.
A 400 is different from a 500
400
The request is invalid.
500
The server failed while handling
a request it should have been
able to process.
401 Unauthorized
The name 401 Unauthorized is slightly misleading to humans.
Its HTTP meaning is primarily:
Authentication is required
or the supplied authentication
is not acceptable.
401 is commonly associated with HTTP authentication
For example, a staging environment protected with HTTP Basic Authentication may initially return:
401 Unauthorized
along with a:
WWW-Authenticate
challenge.
401 and 403 are different
A useful simplified distinction is:
401
Who are you?
Authenticate first.
403
I understand the request,
but you are not allowed
to access this resource.
Application login screens do not necessarily return 401
A normal WordPress:
wp-login.php
page can return:
200 OK
because it is successfully serving the login form.
HTTP authentication and WordPress application authentication are different layers.
403 Forbidden
403 Forbidden means the server understood the request but refuses to fulfill it.
Common WordPress causes include
- file permission rules;
- web-server configuration;
- WAF blocks;
- security plugins;
- CDN firewall rules;
- application permission checks;
- blocked IP addresses.
A 403 may occur before WordPress runs
For example:
Visitor
↓
CDN firewall
↓
403 Forbidden
WordPress never receives the request.
This changes where you debug
If the response headers show the request was blocked by a CDN or proxy, spending two hours editing:
functions.php
is unlikely to impress the firewall into changing its mind.
404 Not Found
404 Not Found means the server cannot find the requested resource.
Typical WordPress cases include:
- deleted post;
- mistyped URL;
- old permalink;
- missing route;
- broken rewrite rules;
- nonexistent attachment URL.
WordPress has dedicated 404 handling
Core’s request processing determines whether the current query represents a missing resource and can send the appropriate 404 status before the theme renders its 404 template.
A 404 is not automatically an emergency
The internet contains bad URLs.
Bots request nonsense continuously.
Examples:
/wp-admin-old/
/phpmyadmin/
/random-malware-path/
/page-that-never-existed/
Those requests returning 404 can be completely correct.
Focus on meaningful 404s
Investigate when a 404 affects:
- an old valid URL;
- an internal link;
- an important backlink;
- a sitemap URL;
- a recently migrated page;
- a resource users genuinely need.
Do not redirect every 404
Automatically redirecting every missing URL to:
/
hides useful errors and produces poor mappings.
A custom 404 page should help users recover
It can include:
- navigation;
- search;
- popular pages;
- homepage link;
- clear explanation.
But the HTTP status should remain:
404 Not Found
405 Method Not Allowed
405 Method Not Allowed means the target resource exists but does not support the request method that was used.
For example:
GET /some-endpoint/
but endpoint accepts only:
POST
The response should identify allowed methods
A 405 response is associated with an:
Allow:
header describing the supported methods.
WordPress Core uses this behavior
For example, Core’s XML-RPC server can reject a non-POST request with:
405 Method Not Allowed
Allow: POST
405 is useful when building REST and custom endpoints
It is more precise than returning:
404
when the endpoint exists but the caller used the wrong method.
409 Conflict
409 Conflict indicates the request conflicts with the current state of the target resource.
This is mainly relevant to APIs and application workflows.
Examples might include:
resource already exists
conflicting state transition
version conflict
409 describes state conflict, not malformed syntax
Compare:
400
Request itself is invalid.
409
Request is understandable,
but conflicts with current state.
410 Gone
410 Gone means the requested resource is no longer available and the condition is intended to be permanent.
410 is more explicit than 404
A simplified distinction:
404
Resource cannot be found.
410
Resource is intentionally gone.
Use 410 for deliberately removed resources with no replacement
Examples can include:
- expired campaign page intentionally removed;
- obsolete resource that should disappear;
- deleted content with no equivalent destination.
Do not use 410 when a replacement exists
If:
/old-guide/
has become:
/new-guide/
then a permanent redirect is usually more useful than declaring the old resource permanently gone without telling clients where it went.
Google accepts both 404 and 410 for removed content
Google’s current crawling documentation recommends returning either 404 or 410 when content has been removed and no suitable replacement exists.
413 Content Too Large
413 Content Too Large, historically called Payload Too Large, means the request body exceeds what the server is willing or able to process.
This can appear during WordPress uploads
For example:
Upload:
200 MB video
Server request limit:
64 MB
→ 413
The limit may exist outside WordPress
Possible layers include:
- Nginx request-size limit;
- Apache configuration;
- CDN limits;
- reverse proxy limits;
- PHP upload limits;
- WordPress/application limits.
Increasing upload_max_filesize may not fix a 413
If Nginx rejects the request before PHP receives it, changing:
upload_max_filesize
inside PHP does nothing.
Find the layer producing the status
This principle appears repeatedly throughout HTTP debugging.
416 Range Not Satisfiable
416 Range Not Satisfiable can occur when a client requests a byte range the resource cannot provide.
For example:
File size:
1,000,000 bytes
Request:
bytes=2,000,000-3,000,000
This is relevant to media delivery
Video/audio seeking and resumable downloads often use Range requests.
Persistent 416 errors can point toward:
- incorrect file-size metadata;
- broken proxy behavior;
- cache inconsistencies;
- truncated files;
- incorrect Range handling.
422 Unprocessable Content
422 Unprocessable Content means the server understands the request syntax and media type but cannot process the instructions it contains.
It can be useful for API validation scenarios.
For example:
Valid JSON syntax
but
invalid business data
422 and 400 overlap in real APIs
Different applications make different choices about validation failures.
What matters is maintaining a consistent documented API contract rather than selecting a status because its name sounds impressively precise.
429 Too Many Requests
429 Too Many Requests means the client has sent too many requests within a given period.
This is a rate-limiting response
Common WordPress-related sources include:
- API rate limits;
- security plugins;
- CDNs;
- WAF rules;
- hosting protection;
- login protection.
429 can include Retry-After
The response can tell the client when it should try again:
HTTP/1.1 429 Too Many Requests
Retry-After: 60
Do not use 403 when the real condition is temporary rate limiting
These statuses communicate different things:
403
Request is forbidden.
429
You are making too many
requests right now.
429 matters to search-engine crawling too
Google’s current crawler documentation treats 429 similarly to server-overload signals and temporarily reduces crawling.
Persistent 429 responses can therefore affect crawling
If a CDN rate-limits legitimate crawlers too aggressively, search engines may receive an inaccurate picture of server capacity.
500 Internal Server Error
500 Internal Server Error is the generic server-error status.
It means the server encountered a condition that prevented it from fulfilling the request and does not have a more appropriate specific 5xx response.
Common WordPress causes include
- PHP fatal errors;
- broken plugin code;
- theme errors;
- memory exhaustion;
- incorrect server configuration;
- corrupted rewrite configuration;
- database-related application failures.
A 500 often means application debugging
Check:
- PHP error logs;
- WordPress debug logs;
- web-server error logs;
- recent plugin/theme changes;
- PHP version compatibility;
- memory limits.
Do not enable public debug output as the permanent solution
Visitors should not receive:
/var/www/example/wp-content/plugins/...
SQL query details
stack traces
server paths
because a plugin crashed.
Log errors privately
Production debugging generally distinguishes:
log errors
from
display errors publicly
500 does not always prove WordPress itself is defective
PHP configuration, server modules and infrastructure can produce the same broad response.
502 Bad Gateway
502 Bad Gateway means a server acting as a gateway or proxy received an invalid response from an upstream server.
A common WordPress architecture looks like this
Browser
↓
Nginx
↓
PHP-FPM
↓
WordPress
If Nginx cannot obtain a valid response from PHP-FPM, the browser may receive:
502 Bad Gateway
WordPress may never get the chance to render anything
Possible causes include:
- PHP-FPM crashed;
- upstream socket unavailable;
- incorrect proxy configuration;
- server overload;
- upstream process terminated.
A CDN can also produce 502
For example:
Visitor
↓
CDN
↓
origin server
↓
invalid origin response
↓
502
Start debugging at the gateway boundary
Look at:
- proxy logs;
- PHP-FPM logs;
- origin availability;
- server resource usage;
- CDN diagnostics.
503 Service Unavailable
503 Service Unavailable means the server is temporarily unable to handle the request.
Typical reasons include:
- maintenance;
- temporary overload;
- temporary service interruption.
503 is the important maintenance status
If a WordPress site is briefly unavailable for maintenance, the server should not pretend the maintenance page is normal permanent content.
A correct pattern is:
HTTP/1.1 503 Service Unavailable
Retry-After: 1800
Retry-After communicates temporary duration
It can tell clients approximately when the resource may become available again.
Google specifically recommends 503 for short temporary shutdowns
The current Google Search guidance for temporarily disabling a site recommends 503 for a short outage and suggests using Retry-After.
Do not return 503 forever
A temporary status used indefinitely eventually stops looking temporary.
Google also warns that prolonged server errors can ultimately cause URLs to leave the index.
Do not return 503 for robots.txt during normal maintenance
Google’s current maintenance guidance specifically recommends keeping:
robots.txt
available rather than returning a 503 for it.
Maintenance Mode uses the correct temporary model
TheOneWP Maintenance Mode can place the public site into maintenance mode while using a 503 Service Unavailable response and Retry-After behavior rather than presenting temporary maintenance content as an ordinary successful page.
For implementation strategy, see WordPress maintenance mode best practices.
503 is not the same as password protection
A staging site protected from public access is not necessarily:
temporarily broken.
It is intentionally restricted.
TheOneWP Site Password Protection solves that different access-control workflow.
504 Gateway Timeout
504 Gateway Timeout means a gateway or proxy did not receive a timely response from an upstream service.
This frequently indicates a slow backend request
For example:
Nginx
waits for PHP-FPM
↓
PHP request runs too long
↓
proxy timeout reached
↓
504 Gateway Timeout
Possible WordPress causes behind a 504 include
- very slow database queries;
- large imports;
- slow external API calls;
- plugin loops;
- resource exhaustion;
- long synchronous processes.
The component reporting 504 is usually the gateway
The slow operation may be inside WordPress, but the status often comes from the server waiting in front of it.
502 vs. 504
A useful simplified distinction:
502 Bad Gateway
Gateway received an invalid
upstream response.
504 Gateway Timeout
Gateway did not receive the
upstream response in time.
Do not fix every 504 by increasing timeouts
If a request takes:
180 seconds
because a database query is catastrophically inefficient, changing the timeout to:
300 seconds
has not necessarily fixed the problem.
You have simply given the catastrophe more time.
Check the underlying workload
Profile:
- database queries;
- external HTTP requests;
- PHP execution;
- memory use;
- server load.
What about 501 Not Implemented?
501 Not Implemented means the server does not support the functionality needed to fulfill the request.
This is uncommon in everyday WordPress page requests.
Do not use 501 for unfinished website features
If your client has not yet approved the portfolio filter, the appropriate status is not:
501 Not Implemented
because your project manager is still waiting for feedback.
What about 451 Unavailable For Legal Reasons?
451 Unavailable For Legal Reasons indicates that access to a resource is unavailable for legal reasons.
This is specialized and uncommon for normal WordPress administration, but it is a standardized HTTP status recognized by current WordPress Core.
HTTP status codes and SEO
Status codes are a fundamental part of how crawlers interpret URLs.
2xx responses normally represent successful content
A public page intended for indexing will usually need a successful response such as:
200 OK
3xx responses communicate URL movement
Permanent redirects tell search engines that another URL should replace the old location.
Temporary redirects communicate a temporary alternative.
4xx responses communicate missing or unavailable resources
For normal removed content:
404
410
are meaningful responses.
5xx responses communicate server failure
Google’s current crawler documentation says that server errors cause crawling to slow temporarily, and URLs that continue returning server errors can eventually be removed from the index.
429 is treated specially by Google
Although 429 is technically a 4xx response, Google treats it as an overload-style signal and reduces crawling similarly to server errors.
Do not intentionally use 500-series errors to remove URLs from search
If content is intentionally gone:
404
or
410
communicates that fact accurately.
A:
500
says the server is broken.
Do not use 403 as an SEO removal mechanism either
Access restriction and content removal are different semantics.
Soft 404s deserve special attention
A soft 404 often looks like:
GET /deleted-product/
HTTP 200 OK
Page body:
"Sorry, this product no longer exists."
The fix depends on what happened to the content
If a replacement exists:
301 → replacement
If there is no replacement:
404
or
410
If the page still exists:
fix the page
and return 200
Status codes should describe reality
This sounds obvious.
It is also the principle behind nearly every correct decision in this guide.
HTTP statuses and WordPress REST API responses
The WordPress REST API also uses HTTP status codes.
A JSON response might look like:
{
"code": "rest_forbidden",
"message": "Sorry, you are not allowed.",
"data": {
"status": 403
}
}
The HTTP status remains important even when the response is JSON
API clients should not need to parse arbitrary human-readable strings to determine whether:
the request succeeded
authentication failed
the resource was missing
the server crashed
Use meaningful REST statuses
Conceptually:
200
Successful retrieval/update
201
Resource created
400
Invalid request
401
Authentication required
403
Authenticated/not permitted
404
Resource not found
409
State conflict
429
Rate limit exceeded
500
Unexpected server failure
Do not return 200 with an error field for everything
This:
HTTP 200
{
"success": false,
"error": "Forbidden"
}
forces every client to invent its own interpretation of whether the HTTP request actually succeeded.
Use the protocol you already have
HTTP status codes exist specifically so clients can understand these outcomes consistently.
How to check a WordPress HTTP status code
Do not rely only on what the browser page looks like.
Use browser developer tools
Open:
Developer Tools
→ Network
reload the page and inspect the main document request.
You can see information including:
- status;
- response headers;
- redirects;
- request method;
- timing.
Use curl
A useful terminal check is:
curl -I https://example.com/page/
This sends a HEAD request and displays response headers.
Example:
HTTP/2 301
location: https://example.com/new-page/
Remember that HEAD and GET can behave differently
For debugging application behavior, you can explicitly test GET:
curl -s -o /dev/null \
-w "%{http_code}\n" \
https://example.com/page/
Inspect full response headers when necessary
curl -i https://example.com/page/
Follow redirects deliberately
For example:
curl -L -I \
https://example.com/old-page/
can help inspect a redirect path.
But also inspect each hop
If you only look at the final:
200 OK
you may miss:
301
↓
302
↓
301
↓
200
along the way.
Use Search Console for Google-specific interpretation
For important URLs, Google’s URL Inspection tooling can help show how Google sees:
- availability;
- indexing;
- canonical information;
- crawl state.
Use server logs when browser evidence is insufficient
Access logs can show:
request
method
path
response status
user agent
timestamp
Error logs show another layer
For example:
PHP fatal error
upstream timeout
permission denied
connection failure
Combine access and error logs
An access log tells you:
GET /checkout/
→ 500
The error log may tell you:
PHP Fatal error:
Allowed memory size exhausted
Status code tells you what happened
The logs help explain:
why.
A practical WordPress status-code troubleshooting workflow
Unexpected response
↓
Confirm actual HTTP status
↓
Check response headers
↓
Identify which layer sent it
↓
Check WordPress/application logs
↓
Check proxy/server/CDN logs
↓
Reproduce request directly
↓
Fix underlying cause
↓
Retest exact status
If the response is 301, 302, 307 or 308
Check:
- Location header;
- whether move is permanent or temporary;
- redirect chain;
- redirect loop;
- method preservation;
- internal links still pointing to old URLs.
If the response is 401
Check:
- HTTP authentication;
- authentication credentials;
WWW-Authenticatechallenge;- proxy authentication rules.
If the response is 403
Check:
- WAF;
- CDN firewall;
- security plugin;
- file permissions;
- web-server rules;
- WordPress capability checks.
If the response is 404
Check:
- whether URL ever existed;
- permalink structure;
- rewrite rules;
- old migration URL;
- deleted content;
- internal links.
If the response is 413
Check:
- proxy request limit;
- web-server request limit;
- PHP upload limit;
- WordPress/application limit.
If the response is 429
Check:
- rate-limit rules;
- WAF;
- CDN;
- API limits;
- request volume;
- legitimate bots being throttled.
If the response is 500
Check:
- PHP logs;
- WordPress debug log;
- recent code changes;
- memory exhaustion;
- plugin/theme failures;
- server configuration.
If the response is 502
Check:
- reverse proxy;
- PHP-FPM;
- origin availability;
- upstream socket;
- CDN connection to origin.
If the response is 503
Determine whether it is:
intentional maintenance
or
unexpected overload/outage.
For intentional maintenance, verify:
- temporary duration;
- useful error page;
Retry-Afterwhere appropriate;- robots.txt remains reachable;
- maintenance does not remain enabled indefinitely.
If the response is 504
Check:
- slow PHP requests;
- slow database queries;
- external API calls;
- proxy timeout settings;
- server load;
- long synchronous jobs.
HTTP status codes during WordPress launch
Launch day is a particularly important time to audit statuses.
See Preparing a WordPress site for launch.
Check important pages return 200
For example:
Homepage
Services
Contact
Products
Blog posts
→ 200 OK
Check migrated URLs return appropriate redirects
Old URL
→ 301
→ new URL
→ 200
Check removed URLs return 404 or 410
Do not accidentally make them:
200 soft 404
Check the custom 404 itself
Request a deliberately nonexistent URL and verify:
404 Not Found
not:
200 OK
Check maintenance mode before using it
Verify the maintenance response is actually:
503 Service Unavailable
rather than relying on the words “Maintenance Mode” printed across the screen.
Check redirect behavior after HTTPS migration
Ideally:
http://example.com/page/
↓
301
https://example.com/page/
↓
200
rather than several unnecessary hops.
Check www and non-www behavior
Choose the intended canonical host and redirect the alternative consistently.
HTTP codes and caching
Status codes can interact with caches.
Some redirect responses may be cached.
Error responses can also be cached depending on infrastructure and headers.
This can confuse debugging
You fix:
301 → wrong URL
but the browser continues using the cached redirect.
Test with a clean client
Use:
- curl;
- private browsing;
- cache disabled in DevTools;
- CDN cache purge where appropriate.
Check multiple cache layers
A WordPress site may involve:
Browser
↓
CDN
↓
Reverse proxy
↓
Page cache
↓
WordPress
The cached status may not come from current WordPress execution
This is especially relevant when a temporary error page remains visible after the application has recovered.
HTTP status codes and robots.txt
The status of:
/robots.txt
deserves special attention.
Do not assume robots.txt is just another webpage
Search-engine crawlers use it to determine crawl permissions.
Server errors on robots.txt can have broader effects
This is one reason Google’s maintenance guidance recommends keeping robots.txt available instead of returning site-wide 503 for that resource.
robots.txt is not access control
See Robots.txt vs. real access control.
A successful robots.txt response does not protect content
It communicates crawler rules.
It does not authenticate visitors.
HTTP status codes and WordPress redirects
Before adding any rule, answer two questions:
Has the resource moved?
Is the move permanent?
If yes and yes
Use a permanent redirect such as:
301
or
308
depending on method requirements.
If yes but temporarily
Use an appropriate temporary redirect such as:
302
or
307
If no replacement exists
Use:
404
or
410
as appropriate.
If the site is temporarily unavailable
Use:
503
rather than pretending every URL permanently disappeared.
A practical status decision tree
Did the request succeed?
│
├── Yes
│ ├── Normal content
│ │ → 200
│ │
│ ├── Resource created
│ │ → 201
│ │
│ └── No response body required
│ → 204
│
└── No
│
├── Resource moved?
│ │
│ ├── Permanently
│ │ → 301 / 308
│ │
│ └── Temporarily
│ → 302 / 307
│
├── Client/access issue?
│ │
│ ├── Authentication required
│ │ → 401
│ ├── Forbidden
│ │ → 403
│ ├── Missing
│ │ → 404
│ ├── Intentionally removed
│ │ → 410
│ └── Rate limited
│ → 429
│
└── Server problem?
│
├── Generic application failure
│ → 500
│
├── Invalid upstream response
│ → 502
│
├── Temporary unavailable
│ → 503
│
└── Upstream timeout
→ 504
A WordPress redirect decision tree
Old URL no longer canonical
│
├── Equivalent replacement exists?
│ │
│ ├── Yes
│ │ │
│ │ └── Permanent move?
│ │ ├── Yes → 301 / 308
│ │ └── No → 302 / 307
│ │
│ └── No
│ │
│ ├── Intentionally removed
│ │ → 410
│ │
│ └── Simply missing
│ → 404
A 5xx debugging decision tree
5xx response
│
├── 500
│ └── Inspect PHP / WordPress /
│ server application errors
│
├── 502
│ └── Inspect gateway and
│ upstream response
│
├── 503
│ └── Maintenance or
│ temporary overload?
│
└── 504
└── Inspect slow upstream
request / timeout
Common HTTP status mistakes on WordPress
Displaying a 404 page with 200 OK
This creates a soft 404.
Redirecting every missing URL to the homepage
A missing resource should not automatically become the homepage merely because both URLs happen to be on the same domain.
Using 302 for a permanent migration forever
If the move is permanent, communicate that explicitly.
Using 301 for a genuinely temporary experiment
Permanent responses can be cached and interpreted as permanent moves.
Ignoring 307 and 308 for method-sensitive requests
POST and API behavior can make method preservation important.
Using 200 for maintenance pages
Temporary maintenance content should not masquerade as the site’s normal successful content.
Using 404 for maintenance
The resources are not missing. The service is temporarily unavailable.
Using 403 to mean “come back later”
Forbidden and temporarily overloaded are different conditions.
Assuming every 500 comes from a plugin
Server configuration and infrastructure can fail too.
Debugging a 502 only inside WordPress
The gateway may be telling you WordPress/PHP never returned a usable response at all.
Fixing a 504 only by increasing timeout values
Sometimes the underlying request is simply too slow.
Increasing PHP upload limits when the request gets 413 before PHP
The rejecting layer may be Nginx, a proxy or CDN.
Treating 401 and 403 as synonyms
Authentication and authorization are different concepts.
Blocking Googlebot with 429 continuously
Search crawlers can interpret persistent rate limiting as server-capacity trouble.
Returning 503 for robots.txt during maintenance
Google specifically recommends keeping robots.txt reachable.
Trusting the page design instead of checking the response
The browser can display “404”, “Maintenance”, “Forbidden” or “Success” regardless of what the actual protocol status says.
WordPress HTTP status code checklist
- Verify normal public pages return
200. - Verify created API resources use an appropriate successful response.
- Use
301or308for permanent moves. - Use
302or307for genuinely temporary redirects. - Use
303where a POST should redirect to a GET resource. - Understand that
304is cache validation, not a URL redirect. - Use real
404responses for missing pages. - Consider
410for intentionally removed resources with no replacement. - Do not return
200for error pages accidentally. - Check HTTP authentication when receiving
401. - Check permissions, WAFs and access rules for
403. - Check supported request methods for
405. - Check server/proxy request limits for
413. - Check Range handling for persistent
416media errors. - Use
429for deliberate rate limiting rather than generic blocking. - Investigate PHP/application errors for
500. - Investigate gateways/upstream responses for
502. - Use
503for short intentional maintenance. - Add
Retry-Afterto temporary503or rate-limit responses where appropriate. - Investigate slow upstream operations for
504. - Do not assume every HTTP response was generated by WordPress.
- Inspect CDN, proxy, web-server and PHP layers when necessary.
- Test status codes with browser DevTools or curl.
- Inspect each redirect hop, not only the final response.
- Monitor redirects and meaningful 404s after migrations.
- Check statuses again immediately after launch.
Quick reference: common WordPress HTTP status codes
200 OK
Normal successful page
201 Created
New resource successfully created
204 No Content
Successful request with no body
206 Partial Content
Partial file/range response
301 Moved Permanently
Permanent redirect
302 Found
Temporary redirect
303 See Other
Redirect to another resource with GET
304 Not Modified
Use cached representation
307 Temporary Redirect
Temporary redirect preserving method
308 Permanent Redirect
Permanent redirect preserving method
400 Bad Request
Invalid request
401 Unauthorized
Authentication required
403 Forbidden
Request understood but refused
404 Not Found
Resource not found
405 Method Not Allowed
Wrong HTTP method
409 Conflict
Request conflicts with current state
410 Gone
Resource intentionally removed
413 Content Too Large
Request body too large
416 Range Not Satisfiable
Requested byte range unavailable
422 Unprocessable Content
Request understandable but invalid semantically
429 Too Many Requests
Rate limit exceeded
500 Internal Server Error
Generic server/application failure
502 Bad Gateway
Invalid upstream response
503 Service Unavailable
Temporary outage or maintenance
504 Gateway Timeout
Upstream response took too long
Related WordPress HTTP, redirect and launch guides
For the wider HTTP, migration, redirect and production-management cluster, continue with:
- 301 vs. 302 vs. 410: which redirect to use?
- Reading a redirect access log
- How to migrate WordPress URLs safely
- Preparing a WordPress site for launch
- WordPress maintenance mode best practices
- Robots.txt vs. real access control
- WordPress staging site best practices
- Why serialized data breaks naive WordPress migrations
- What is an XML sitemap and why does it matter?
- Redirect Manager
- Maintenance Mode
- Site Password Protection
Final thoughts
HTTP status codes are the machine-readable version of what happened to a WordPress request.
The page design tells a human:
We couldn't find this page.
The HTTP response should tell the client:
404 Not Found
The maintenance page tells a human:
We'll be back shortly.
The response should tell automated systems:
503 Service Unavailable
A migration tells users:
This page has moved.
The response should communicate whether that move is:
permanent
or
temporary.
Once that distinction is understood, HTTP troubleshooting becomes considerably more systematic.
A 403 points you toward authorization, firewall or access rules.
A 404 points you toward resource resolution and routing.
A 413 points you toward request-size limits.
A 429 points you toward rate limiting.
A 500 points you toward application or server execution.
A 502 points you toward a gateway and its upstream.
A 503 describes temporary unavailability.
A 504 tells you the upstream response took too long.
TheOneWP Redirect Manager can manage intentional URL redirects, while Maintenance Mode can use the correct temporary 503 response during maintenance instead of allowing an interruption page to masquerade as normal content.
The practical rule is simple:
Make the HTTP status describe
what actually happened.
Then make the visible page useful to the human receiving it.
Doing those two things in the opposite order is how websites end up with gorgeous custom error pages proudly returning 200 OK, because apparently even failure needs excellent branding while lying to the protocol.

