For some reason, WordPress will send a 200
HTTP response status code, or OK
, when a login attempt has failed. Why not send a 403
status code, which is designed specifically to say you can’t be here, or forbidden
, actually. There’s even a better alternative to 403
, but stay with me.
I came about this bit of information while reading this post by Konstantin Kovshenin. And was able to confirm it myself by logging into this site incorrectly, as you can see in the featured image above. wp-login.php is returned as 200 OK
and is circled in red.
So, as Konstantin suggested, we can use this code to send a proper 403 Forbidden
status code on a failed login attempt:
<?php function my_login_failed_403() { status_header( 403 ); } add_action( 'wp_login_failed', 'my_login_failed_403' ) ?>
But why send a 403
, which is Forbidden
? It’s not truly a forbidden page, as people have a legit reason to be there, even if they can’t remember their password.
So, sending 401 Unauthorized
as the HTTP response status code may be even better.
<?php function my_login_failed_401() { status_header( 401 ); } add_action( 'wp_login_failed', 'my_login_failed_401' ); ?>
So, you can use either of those, the first chunk to send a 403 Forbidden
response, and the second for sending a 401 Unauthorized
response code.

Either could go in the functions.php file for your theme, or more likely, in your WordPress functionality plugin.
You can find a good list of HTTP response codes at the Mozilla Developer Network site.
Well, now what?
Work with Me
I'm available for hire and always taking new clients, big and small. Got a project or an idea you'd like to discuss? Startup plan but no developer to make it happen? Just get in touch, I'd love to see if I can help you out!
Leave some Feedback
Got a question or some updated information releavant to this post? Please, leave a comment! The comments are a great way to get help, I read them all and reply to nearly every comment. Let's talk. 😀
Longren.io is proudly hosted by DigitalOcean

401 has a specific meaning within HTTP/1.1, and the spec says a 401 response MUST include a WWW-Authenticate header, and is intended to start HTTP authentication. 403 is less “semantically” correct, though. There’s no good status for failed HTTP forms, but a few people seem to be leaning toward something between 420-422 (422 is “Unprocessable Entity” but the WebDAV definition isn’t far off: http://tools.ietf.org/html/rfc4918#section-11.2).
Thanks for the details James! I’ve never really looked into the 420-422 range, but am now. 🙂