2026年11月12日
2026年11月12日
Restrict wp-admin by IP with .htaccess (Apache 2.4, keep admin-ajax)
This article is a localized edition of the Japanese original. Read the Japanese original
If you allow the WordPress admin area (/wp-admin/) to open only from specific IP addresses, login attempts from anywhere else are stopped at the web server before they reach WordPress. This article shows how to set up IP address restrictions with Apache's .htaccess, together with the exceptions you need so the public side of your site keeps working.
A mistake in the configuration can lock you out of the admin area too. Before you start, make sure you can edit .htaccess over FTP, SFTP or your hosting company's file manager.
Where this method works
- Your web server is Apache (or LiteSpeed, which also reads
.htaccess). Nginx does not read.htaccess, so this method has no effect there. - To use
Requirein.htaccess, the server must allowAllowOverride AuthConfig(orAll). If it is not allowed, the directive causes a 500 error. Most shared hosting plans allow it. - Your connection's IP address does not change (a static IP, an office line, a VPN, and so on). On connections whose IP address changes, such as most home internet lines, you get locked out every time it changes (see below).
Step 1: Check your IP address
On the computer you use to open the admin area, run the following. You can also open a website that shows your IP address in the browser.
# IPv4 address
curl -s https://api.ipify.org
# Check for IPv6 (returns an IPv6 address if your connection supports IPv6)
curl -s https://api64.ipify.org
If your connection supports IPv6, you may reach the server over IPv6. In that case, you also need to allow your IPv6 address (or its prefix), or you will get a 403.
Step 2: Create wp-admin/.htaccess and restrict IP addresses
Create a .htaccess file inside the wp-admin folder. (WordPress core does not ship this file. If one already exists, check its contents before adding to it.) The Apache 2.4 syntax looks like this:
# wp-admin/.htaccess
# Allowed IP addresses (replace the example values with your own)
Require ip 203.0.113.10 198.51.100.0/24 2001:db8:1234::/48
# Files that the public side of the site also calls must stay open to everyone
<Files admin-ajax.php>
Require all granted
</Files>
<Files admin-post.php>
Require all granted
</Files>
- List IP addresses after
Require ip, separated by spaces. CIDR notation such as198.51.100.0/24and IPv6 addresses also work. admin-ajax.phpis also called by features on the public side of the site, such as contact form submissions, filtered search and WooCommerce cart updates. If you restrict it, those features stop working.admin-post.phpis sometimes used to receive form submissions from visitors who are not logged in (for example, plugins that use hooks starting withadmin_post_nopriv_). Even if you do not use it, allowing it rarely causes problems.
The Order Deny,Allow, Deny from all and Allow from … syntax belongs to Apache 2.2. In Apache 2.4 it works only when the compatibility module (mod_access_compat) is enabled, and mixing it with Require easily leads to unexpected results, so use Require for new rules.
Step 3: Restrict wp-login.php as well
wp-login.php sits in the WordPress root, not in the wp-admin folder, so the rules from step 2 do not protect it. Add the following to the root .htaccess. Put it outside (above) the # BEGIN WordPress to # END WordPress block, which WordPress rewrites.
# Root .htaccess (place above # BEGIN WordPress)
<Files wp-login.php>
Require ip 203.0.113.10 198.51.100.0/24 2001:db8:1234::/48
</Files>
wp-login.php also handles "forgot password" requests and the password form for password-protected pages. On sites that use user registration or password-protected pages, keep in mind that outside visitors will no longer be able to use these.
Step 4: Test the setup
From a connection that is not allowed (for example, a smartphone on mobile data), confirm the following results.
# Should return 403 Forbidden
curl -I https://example.com/wp-admin/
curl -I https://example.com/wp-login.php
# Should NOT return 403 (without parameters, WordPress returns 400)
curl -I https://example.com/wp-admin/admin-ajax.php
From an allowed connection, open /wp-admin/ in your browser and confirm that the login screen appears as usual. Also try the features on the public side that use admin-ajax.php, such as contact forms and search.
If you use Cloudflare or a reverse proxy
When traffic goes through Cloudflare or a load balancer, Apache sees the IP address of the proxy as the client. In that state, specifying your own IP address in Require ip never matches. You need Apache's mod_remoteip to restore the original client address from the header the proxy sends (CF-Connecting-IP for Cloudflare). On shared hosting, support for this differs between hosting companies, so check your control panel's documentation or support pages.
If you use Cloudflare, you can also restrict /wp-admin/ and /wp-login.php with Cloudflare's own access controls (WAF custom rules or Cloudflare Access).
If your IP address changes
If your connection's IP address changes, the following approaches suit you better than IP restrictions:
- Add Basic authentication to the admin area (a second username and password that works regardless of IP address)
- Set up a VPN and allow only the VPN's exit IP address
- Limit login attempts or add two-factor authentication
Some hosting companies offer a control-panel feature such as "restrict admin access from outside the country". If you combine it with .htaccess rules, it becomes hard to tell which one blocked you, so keep a record of where you added restrictions.
How to recover if you lock yourself out
If your IP address changes or a typo causes a 403 or 500 error, do one of the following over FTP, SFTP or the file manager:
- Rename
wp-admin/.htaccessto something likehtaccess-off(this removes the restriction) - Delete the
<Files wp-login.php>block you added to the root.htaccess
Once you are back in the admin area, check your current IP address, update Require ip, and rename the file back.
Summary
- In
wp-admin/.htaccess, list the allowed IP addresses withRequire ip, and excludeadmin-ajax.phpandadmin-post.phpwithRequire all granted - Restrict
wp-login.phpin the root.htaccesswith a<Files wp-login.php>block placed outside# BEGIN WordPress - In Apache 2.4, write rules with
Require, notOrder,AllowandDeny - With IPv6, proxies such as Cloudflare, or connections whose IP address changes, review the values you allow or choose another method
- If you get locked out, rename
.htaccessover FTP or similar to lift the restriction
Related articles
- How to add Basic authentication to the WordPress admin area
- Why only wp-admin returns 403 Forbidden and how to fix it
- How to restrict the login page by IP address
Questions about WordPress? The publisher of this site is based in Japan and replies in Japanese. Contact (Japanese)