You load your site, or visit an API endpoint your app relies upon, and instead of a page you find a brief, unhelpful message: 401 Unauthorized. Sometimes a browser password box appears. Other times, a blank white page presents only that number. In either case, visitors are shut out, and if the error strikes your admin area, even you are left at the threshold.
The good news is that a 401 is one of the more honest HTTP responses. It tells you something specific. The server received your request, understood it, and decided you had not proven your identity. This problem is much narrower than a 500 error and is usually resolved in minutes once you know which layer is asking for credentials.
In this post we will explain what the 401 HTTP code means, describe the causes most often seen on WordPress and other CMS sites, and provide a step-by-step process for fixing it in your browser, server configuration, and REST API calls. We will also look at the case that matters most to us, when a sudden wave of 401s signals a deeper compromise rather than a simple configuration mistake.
Contents:
HTTP 401 Unauthorized is a response status code that signals authentication has failed. The server received a valid request, but no acceptable credentials came with it. These may be missing, malformed, expired, or simply incorrect, so the server refuses to serve the resource.
It belongs to the 4xx family, which the HTTP specification calls client errors. That label deserves a second look, as it can be misleading. A 4xx code does not mean the visitor acted carelessly. Instead, it points to a problem in the request, not in the server’s ability to process it. Even a misconfigured rule on your server can produce 401s for well-behaved visitors throughout the day.
There is a second quirk in the naming. “Unauthorized” is really better called “unauthenticated.” A 401 means the server does not know who you are. If the server does know, but still denies access, it returns a 403 instead. We cover that code separately in our guide to HTTP error 403.
One technical detail is useful for diagnosis. A proper 401 response should include a WWW-Authenticate header that names the authentication scheme the server expects, such as Basic or Bearer. This header prompts a browser to display a username and password box when it encounters a 401. If you spot that header in the response, it reveals exactly which system is challenging you.
The wording depends on the server, the browser, and whatever is sitting in front of your site, so the same underlying problem shows up with different faces. Common variations include:
401 UnauthorizedHTTP Error 401 - Unauthorized401 Authorization RequiredAccess denied due to invalid credentialsFor API and application traffic you won’t see any of that. You’ll get a JSON or XML body with an error message, a 401 in your HTTP client’s logs, and a failed job somewhere downstream.
The practical consequence is the same in both cases. Human visitors hit a dead end and leave, which costs you trust and conversions. Search crawlers treat the URL as inaccessible, so if a 401 covers pages that are supposed to be public, those pages can drop out of the index while it persists. And if the affected URL is your own login or admin path, your ability to fix anything else on the site is blocked until the 401 is resolved.
In our experience the causes cluster into a handful of layers, and identifying the layer is most of the work. Some are mundane credential problems. Others are configuration, and a few are security events.
.htaccess and an .htpasswd file on Apache or equivalent directives on Nginx, returns 401 by design. It breaks in predictable ways. The password file path may no longer exist, the hash format may be unreadable, file permissions might block access, or protection could remain on a staging directory after it goes live.Authorization header, cache an authenticated response, or apply an access rule you’ve forgotten about. Protected paths combined with aggressive caching are a classic source of intermittent, difficult-to-reproduce 401s.Work from the cheapest check to the most invasive. Stop as soon as the error clears.
WWW-Authenticate.www variant if both are in use./wp-admin/ only, or on one API route only, narrows the search dramatically compared to a site-wide 401..htaccess and server auth config. Look for AuthType, AuthUserFile, and Require directives (or Nginx auth_basic blocks). Confirm the password file path is correct and readable. Temporarily comment out the block, reload, and see whether the 401 disappears. If it does, you have confirmed server-level auth as the culprit. Keep a backup of the file before editing.plugins directory over SFTP or in your host’s file manager to force a bulk deactivation, then rename it back and work through plugins individually. Switching temporarily to a default theme rules out theme-level interference.API 401s are rarely mysterious once you look at the actual request rather than the client library’s error message. Log the full outbound request — minus secrets — and check these in order.
Authorization header actually arriving?Some proxies and server configurations drop it. On Apache with CGI/FastCGI setups, the header may need to be passed through explicitly. Hit the endpoint with curl from the same network to compare.
Authorization: Bearer <token> and Authorization: Basic <base64> are not interchangeable. The WWW-Authenticate header on the 401 response tells you which one the endpoint wants.
Short-lived tokens need a refresh path. If your integration worked for a while and then stopped at a regular interval, assume expiry first.
For the WordPress REST API specifically: cookie-based authentication also requires a valid nonce sent with the request, so a logged-in session alone isn’t enough for write operations from external contexts. Application passwords are the usual choice for server-to-server calls, and they must belong to a user whose role actually has the capability for that endpoint — a token with the wrong user attached produces a 401 or a permissions error that reads like one. Also confirm you’re calling the right base path, since a rewrite or a plugin can change where REST routes live.
Automated requests to admin or API paths can trip firewall rules. Allowlisting the IP or the specific route for your integration fixes it, and this is better than loosening the rule globally. If your API client is hammering an endpoint, check for rate limiting as well. That usually appears as HTTP 429 instead of 401, which makes it easier to tell the two situations apart.
Most 401s are configuration. A few are not, and the pattern is what gives them away.
Treat a 401 as a possible security event when it appears suddenly without a corresponding change on your side, when legitimate administrators are locked out while the front end works normally, when a password box appears on a path you never protected, or when 401s spike across many URLs at once. Another signal we take seriously is when your own credentials stop working and a password reset does not restore access.
Why would an attacker cause 401s at all? Usually not deliberately. Injected code that hooks authentication, redefines the login handler, or adds an access check can break authentication as a side effect of maintaining its own backdoor. In other cases the 401s are collateral damage from a cleanup that removed part of a malicious plugin but left its hooks in place. And if someone has added their own password protection to a directory, that’s an attempt to keep others out of a foothold they’ve established.
If 401 errors spike across your site after a suspected incident, do not just clear the error. Find out what changed. Scan the site for malware, compare core, plugin, and theme files against known-good copies, and look specifically at the files that run on every request. Check items like the theme’s functions.php, the must-use plugins directory, wp-config.php, and recently modified files anywhere under your web root. Then audit accounts. Review the user list for administrators you do not recognize, check the last-modified times on user records if your setup logs them, rotate every password and API key, and revoke application passwords and sessions.
One caveat worth stating plainly: a 401 on its own is not evidence of a hack. It is a prompt to investigate. The combination of unexplained authentication failures and unexpected file changes is what should move you from troubleshooting to incident response.
A few habits remove most of the recurring causes.
Vary and cache-control behavior on those routes is correct..htaccess, server config, SSO, or a membership plugin should be exercised against a real login and a real API call before it reaches production.A 401 is a narrow, legible message. Something asked for credentials and did not get acceptable ones. Find out which layer did the asking, whether it was a browser session, server directive, plugin, proxy, or API endpoint, and the fix usually follows in a step or two. Check credentials and cookies first, then server auth config, then caches and the layers in front of your site, then plugins, and read your logs before you start changing things.
The part that’s easy to skip is the question behind the error. If authentication broke and nobody changed anything, treat that as worth investigating rather than clearing. Scanning for malware, verifying file integrity, and reviewing your administrator accounts turns a one-off fix into something closer to assurance that the 401 wasn’t a symptom of a larger problem.
If you are troubleshooting other status codes as well, our explanations of 500 internal server errors and 502 bad gateway cover the server-side failures that often appear in the same week as a configuration change.
It means authentication failed. The server received and understood your request but found no acceptable credentials attached. They may be missing, expired, or incorrect, so the server refused to return the resource. Despite the word “Unauthorized,” a 401 really means unauthenticated. The server does not yet know who you are.
A 401 means the server could not authenticate you and will accept another attempt with valid credentials, which is why it often triggers a login prompt. A 403 means authentication is not the issue. The server knows who you are, or does not care, and is refusing access to that resource outright. Supplying credentials will not help.
Injected code can hook authentication functions, replace the login handler, or add password protection to admin paths, locking out legitimate users while a backdoor keeps working. Scan for malware, compare core and plugin files against known-good copies, check must-use plugins, then rotate passwords, API keys, and sessions.
Log the actual outbound request. Confirm the Authorization header reaches the server and isn’t stripped by a proxy, that the scheme matches what the WWW-Authenticate header asks for, and that the token hasn’t expired. For the WordPress REST API, cookie authentication also needs a valid nonce, and application passwords need a user with the right capability.
Technically it is a 4xx client error, meaning the issue is in the request rather than in the server’s ability to process it. In practice, the root cause is often on the server side. A misconfigured .htaccess rule, a stale password file, a proxy dropping headers, or a plugin conflict can all be responsible. Be sure to investigate both sides.
A 401 tells crawlers the URL is inaccessible, so pages meant to be public can lose visibility while the error persists. Intentional 401s on admin, staging, or API paths are fine and expected. The risk comes from accidental protection on public URLs, which is worth catching with status-code monitoring.