How to block an IP with .htaccess?
The .htaccess file is one of the most powerful tools available to web server administrators on Apache servers. It allows fine-grained control over access to your site without touching the main server configuration. Among its most common uses: blocking unwanted IP addresses — malicious bots, scrapers, attackers, or simply visitors you want to restrict. Here are all the available methods, from the simplest to the most advanced.
Prerequisites: enabling mod_authz_host
IP access control directives in .htaccess require the Apache mod_authz_host module to be enabled on your server. This is the default on virtually all shared hosting environments and modern Apache servers. If you manage your own server, check with:
apache2ctl -M | grep authzAlso note that the syntax differs slightly between Apache 2.2 and Apache 2.4 (the current version). Both syntaxes are shown below.
Blocking a single IP
This is the simplest case. Add these lines to your .htaccess file at the root of your site:
Apache 2.4 (current syntax):
<RequireAll>
Require all granted
Require not ip 123.456.789.0
</RequireAll>Apache 2.2 (legacy syntax):
Order Allow,Deny
Allow from all
Deny from 123.456.789.0Replace 123.456.789.0 with the IP address you want to block. The visitor will receive a 403 Forbidden error.
Blocking multiple IPs simultaneously
You can add as many addresses as needed, listed on the same line or on separate lines:
Apache 2.4:
<RequireAll>
Require all granted
Require not ip 123.456.789.0
Require not ip 98.76.54.32
Require not ip 11.22.33.44
</RequireAll>Apache 2.2:
Order Allow,Deny
Allow from all
Deny from 123.456.789.0 98.76.54.32 11.22.33.44Blocking an IP range (subnet)
If you need to block an entire block of addresses — for example all IPs from an ISP or a data centre — you can use CIDR notation or the subnet prefix:
By prefix (all IPs starting with 123.456.789):
<RequireAll>
Require all granted
Require not ip 123.456.789
</RequireAll>By CIDR notation (/24 block, i.e. 256 addresses):
<RequireAll>
Require all granted
Require not ip 123.456.789.0/24
</RequireAll>Other common mask examples:
- /32 — a single IP
- /24 — 256 addresses (e.g. 123.456.789.0 to 123.456.789.255)
- /16 — 65,536 addresses (e.g. 123.456.0.0 to 123.456.255.255)
- /8 — 16 million addresses (e.g. 123.0.0.0 to 123.255.255.255)
Blocking an IP on a specific directory
If you want to block an IP's access only to a subdirectory of your site (for example your admin area), place a .htaccess file in that specific directory with the blocking rule:
<RequireAll>
Require all granted
Require not ip 123.456.789.0
</RequireAll>Good to know: you can also use <Directory>, <Files> or <Location> blocks directly in the httpd.conf or apache2.conf file for even more precise control — for example blocking an IP on a specific file only. This approach is more performant than .htaccess because it does not require Apache to read the file on every request.
Whitelisting: allowing only certain IPs
The reverse operation is also possible: only allowing access to one or more specific IPs and blocking everything else. This is particularly useful for protecting an admin interface:
Apache 2.4:
Require ip 123.456.789.0
Require ip 98.76.54.32Apache 2.2:
Order Deny,Allow
Deny from all
Allow from 123.456.789.0
Allow from 98.76.54.32Any unlisted IP will receive a 403 error. Note that if your IP is dynamic (it changes with each connection), this approach may lock you out — prefer a whitelist by subnet range instead.
Redirecting a blocked IP instead of returning a 403
Instead of displaying a raw 403 error, you can redirect blocked IPs to another page — a custom error page or even another URL:
RewriteEngine On
RewriteCond %{REMOTE_ADDR} ^123.456.789.0$
RewriteRule ^ /access-denied.html [R=302,L]Note the escaping of dots with . in the RewriteCond condition — dots have special meaning in regular expressions (they match any character), so they must be escaped to match a literal dot only.
Blocking by User-Agent instead of IP
Some malicious bots or scrapers regularly change their IP but keep the same User-Agent. In this case, blocking by User-Agent is more effective:
RewriteEngine On
RewriteCond %{HTTP_USER_AGENT} ^(BadBot|EvilScraper|MaliciousSpider) [NC]
RewriteRule .* - [F,L]The [F] flag returns a 403 error, [NC] makes the comparison case-insensitive. You can add as many User-Agents as needed by separating them with |.
| Use case | Recommended method | Key syntax |
|---|---|---|
| Block a single IP | Require not ip | Require not ip 1.2.3.4 |
| Block multiple IPs | Require not ip (multiple) | Require not ip 1.2.3.4 (repeated) |
| Block a /24 range | CIDR notation | Require not ip 1.2.3.0/24 |
| Whitelist specific IPs | Whitelist | Require ip 1.2.3.4 |
| Redirect instead of blocking | RewriteRule | RewriteCond %{REMOTE_ADDR} |
| Block by User-Agent | RewriteRule + HTTP_USER_AGENT | RewriteCond %{HTTP_USER_AGENT} |
Good to know: changes made to the .htaccess file take effect immediately in Apache, without a server restart. However, a malformed .htaccess file can make your site entirely inaccessible with a 500 error. Always test your changes in a development environment or back up the original file before any production changes. If your site returns a 500 error after modification, immediately restore the previous version of the file.
Nicolas,