IPcost

How to block an IP with .htaccess?

Nicolas Nicolas,


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 authz

Also 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.0

Replace 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.44

Blocking 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.32

Apache 2.2:

Order Deny,Allow
Deny from all
Allow from 123.456.789.0
Allow from 98.76.54.32

Any 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 caseRecommended methodKey syntax
Block a single IPRequire not ipRequire not ip 1.2.3.4
Block multiple IPsRequire not ip (multiple)Require not ip 1.2.3.4 (repeated)
Block a /24 rangeCIDR notationRequire not ip 1.2.3.0/24
Whitelist specific IPsWhitelistRequire ip 1.2.3.4
Redirect instead of blockingRewriteRuleRewriteCond %{REMOTE_ADDR}
Block by User-AgentRewriteRule + HTTP_USER_AGENTRewriteCond %{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.