Title: EDH Bad Bots
Author: EncodeDotHost
Published: <strong>Gwengolo 3, 2025</strong>
Last modified: Ebrel 13, 2026

---

Search plugins

![](https://ps.w.org/edh-bad-bots/assets/icon.svg?rev=3355590)

# EDH Bad Bots

 By [EncodeDotHost](https://profiles.wordpress.org/encodedothost/)

[Download](https://downloads.wordpress.org/plugin/edh-bad-bots.zip)

 * [Details](https://bre.wordpress.org/plugins/edh-bad-bots/#description)
 * [Reviews](https://bre.wordpress.org/plugins/edh-bad-bots/#reviews)
 *  [Installation](https://bre.wordpress.org/plugins/edh-bad-bots/#installation)
 * [Development](https://bre.wordpress.org/plugins/edh-bad-bots/#developers)

 [Support](https://wordpress.org/support/plugin/edh-bad-bots/)

## Description

EDH Bad Bots is an intelligent bot detection and blocking system that protects your
WordPress site from unwanted crawlers and malicious bots. Unlike traditional blocking
methods that rely on user agent strings (which can be easily spoofed), this plugin
uses a honeypot technique to identify and block bots that don’t respect your site’s`
robots.txt` directives.

### Key Features

 * **Automatic Bot Detection**: Identifies bad bots using a hidden trap URL technique
 * **Smart Blocking System**: Blocks misbehaving bots with configurable duration(
   default 30 days)
 * **Advanced DNS Resolution**: PTR record lookups with DNS over HTTPS (DoH) support
   for hostname identification
 * **Dual-Level Blocking**: Server-level `.htaccess` blocking AND PHP-level blocking
   for maximum effectiveness
 * **Configurable Blocking Methods**: Choose between `.htaccess` blocking (Apache)
   or PHP-only blocking (Nginx compatible)
 * **IP Whitelist Management**: Protect trusted IPs from ever being blocked
 * **Enhanced Admin Interface**: Clean dashboard with hostname display, manual hostname
   updates, and debug tools
 * **Background Processing**: Automated hostname resolution via WordPress cron jobs
 * **Zero False Positives**: Legitimate search engine bots that follow robots.txt
   rules are never affected
 * **Database Optimization**: Automatic cleanup of expired blocks to maintain performance
 * **Security-First Design**: All forms include proper nonce verification and user
   capability checks

### How It Works

The plugin implements a sophisticated honeypot system:

 1. **Trap URL Generation**: Creates a unique, hidden URL specific to your domain
 2. **Robots.txt Integration**: Automatically adds a `Disallow` rule for the trap URL
 3. **Hidden Link Placement**: Places an invisible link to the trap URL in your site’s
    footer
 4. **Bot Detection**: When bad bots ignore robots.txt and follow the hidden link, 
    they’re identified
 5. **Automatic Blocking**: Detected bot IPs are blocked with configurable duration
    and immediate effect
 6. **Hostname Resolution**: PTR record lookups identify the hostname/organization 
    behind blocked IPs
 7. **Legitimate Bot Protection**: Good bots (like Googlebot) respect robots.txt and
    never trigger the trap

### Configuration

### Admin Dashboard

Access the plugin dashboard at **Tools > Bad Bots** in your WordPress admin:

#### Whitelisted IPs Tab

 * Add IP addresses that should never be blocked
 * Remove IPs from the whitelist
 * View all currently whitelisted addresses with timestamps

#### Blocked Bots Tab

 * View all currently blocked IP addresses with hostnames
 * See when each IP was blocked and when the block expires
 * Manually update missing hostnames for better identification
 * Force refresh all hostnames to clear cache and re-resolve
 * Debug hostname resolution issues (when WP_DEBUG is enabled)
 * Manually unblock IPs if needed

#### Options Tab

 * **`.htaccess Blocking`**: Enable/disable server-level IP blocking via `.htaccess`
   file
 * **Block Duration**: Configure how many days to block detected bots
 * Configure blocking method based on your server setup (Apache vs Nginx)
 * Server-level blocking bypasses caching for immediate effect

#### Help Tab

 * Detailed explanation of how the plugin works
 * Best practices for managing IPs
 * Information about `.htaccess` blocking options
 * Unique trap URL for caching plugin exclusion

### Requirements

 * WordPress 6.2 or higher
 * PHP 7.4 or higher
 * MySQL 5.6 or higher
 * Apache server (for `.htaccess` blocking) or Nginx (PHP-only blocking)
 * Writable `.htaccess` file (if using Apache server-level blocking)

### Technical Details

### Database Tables

The plugin creates two custom database tables:

 * `wp_edhbb_blocked_bots`: Stores blocked IP addresses with expiration dates and
   hostnames
 * `wp_edhbb_whitelisted_ips`: Stores permanently whitelisted IP addresses

### DNS Resolution System

The plugin includes an advanced DNS lookup system:

#### DNS over HTTPS (DoH) Support

 * **Primary providers**: Cloudflare DNS, Google DNS
 * **Secure queries**: HTTPS-encrypted DNS requests for enhanced privacy
 * **Fallback system**: Automatic fallback to traditional DNS methods

#### PTR Record Lookups

 * **Reverse DNS**: Converts IP addresses to hostnames for better identification
 * **IPv4 and IPv6 support**: Full support for both IP versions
 * **Caching**: Results cached for 1 hour to improve performance
 * **Background processing**: Automated hostname resolution via WordPress cron

### Blocking Methods

The plugin offers two blocking approaches:

#### 1. Server-Level Blocking (`.htaccess`)

 * **Default method** for Apache servers
 * Blocks IPs at the server level before WordPress loads
 * Bypasses caching plugins for immediate effect
 * More efficient and faster blocking
 * Automatically manages `.htaccess` file with unique markers
 * Safe cleanup on plugin deactivation

#### 2. PHP-Level Blocking

 * **Alternative method** for Nginx or when `.htaccess` is unavailable
 * Blocks IPs during WordPress initialization
 * Compatible with all web servers
 * May be affected by caching plugins
 * No server configuration files modified

### Security Features

 * **Nonce Verification**: All forms use WordPress nonces for CSRF protection
 * **Capability Checks**: Only users with `manage_options` capability can access
   admin features
 * **Input Sanitization**: All user inputs are properly sanitized and validated
 * **SQL Injection Protection**: All database queries use prepared statements
 * **Safe `.htaccess` Management**: Uses unique markers and automatic cleanup

### Performance Optimization

 * **Automatic Cleanup**: Expired blocks are automatically removed from the database
 * **Efficient Queries**: Database operations are optimized for minimal performance
   impact
 * **Smart Loading**: Admin assets only load on the plugin’s admin page
 * **Server-Level Blocking**: `.htaccess` blocking prevents blocked requests from
   reaching PHP
 * **Whitelist Filtering**: Whitelisted IPs are excluded from `.htaccess` rules 
   automatically
 * **DNS Caching**: Hostname lookups cached to reduce DNS query overhead
 * **Background Processing**: Hostname resolution runs in background to avoid delays

### API Hooks

### Actions

 * `plugins_loaded`: Plugin initialization
 * `init`: Early request blocking check
 * `template_redirect`: Bot trap detection
 * `wp_footer`: Hidden link injection
 * `admin_menu`: Admin page registration
 * `edhbb_update_hostnames_cron`: Background hostname resolution

### Filters

 * `robots_txt`: Adds disallow rule to robots.txt

### File Structure

    ```
    `
    ```

edh-bad-bots/
 ├── admin/ │ └── views/ │ └── admin-display.php # Admin interface
HTML ├── assets/ │ ├── css/ │ │ └── admin-style.css # Admin page styling │ └── js/
│ └── admin-script.js # Admin page JavaScript ├── includes/ │ ├── class-edhbb-admin.
php # Admin functionality │ ├── class-edhbb-blocker.php # Bot detection and blocking
│ ├── class-edhbb-database.php # Database operations │ └── class-edhbb-dnslookup.
php # DNS/PTR lookup system ├── edh-bad-bots.php # Main plugin file ├── LICENSE 
└── readme.txt `

### Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

### Development Setup

 1. Clone the repository to your WordPress plugins directory
 2. Ensure you have a WordPress development environment running
 3. Activate the plugin and test your changes

### License

This project is licensed under the GPL v3 or later.

### Author

**EncodeDotHost**
 – Website: [https://encode.host](https://encode.host) – GitHub:
[@EncodeDotHost](https://github.com/EncodeDotHost)

### Contributors

 * [@nbwpuk](https://github.com/nbwpuk)

### Support

For support, please visit [https://encode.host](https://encode.host) or create an
issue on the GitHub repository.

## Screenshots

 * [[
 * Allow list management
 * [[
 * Block list management with hostname display
 * [[
 * Options Page with configurable settings

## Installation

 1. Upload the `edh-bad-bots` folder to your `/wp-content/plugins/` directory
 2. Activate the plugin through the ‘Plugins’ menu in WordPress
 3. The plugin works immediately – no configuration required!
 4. Optionally, visit **Tools > Bad Bots** to manage whitelisted IPs and view blocked
    bots

## FAQ

### Will this block legitimate search engines?

No! Legitimate search engines like Google, Bing, and others respect robots.txt files
and will never hit the trap URL.

### How long are bots blocked for?

Bots are blocked for a configurable duration (default 30 days) that you can adjust
in the Options tab. You can manually unblock them earlier if needed.

### Can I protect my own IP address?

Yes! Add your IP address to the whitelist in the admin panel to ensure you’re never
blocked.

### What’s the difference between .htaccess and PHP blocking?

.htaccess blocking (default) blocks bots at the server level before WordPress loads,
making it faster and more effective. PHP blocking works during WordPress initialization
and is compatible with Nginx servers.

### What is hostname resolution and why is it useful?

The plugin performs PTR record lookups to identify the hostname/organization behind
blocked IP addresses. This helps you understand what types of bots are being blocked(
e.g., “crawl-66-249-66-1.googlebot.com” vs unknown IPs) for better analysis and 
decision-making.

### How does the DNS over HTTPS feature work?

The plugin uses secure HTTPS-encrypted DNS queries via providers like Cloudflare
and Google DNS for enhanced privacy and reliability when resolving hostnames. It
automatically falls back to traditional DNS methods if DoH is unavailable.

### Does this affect site performance?

The plugin is designed for minimal performance impact. Server-level `.htaccess` 
blocking actually improves performance by stopping blocked requests before they 
reach PHP. DNS lookups are cached and processed in the background to avoid delays.

### Will this work with caching plugins?

Yes! Server-level `.htaccess` blocking bypasses caching entirely, ensuring blocked
bots are stopped immediately. PHP-level blocking may be affected by some caching
configurations. To ensure the bot trap works correctly, you should exclude the unique
trap URL from your caching plugin. You can find this URL in the “Help” tab of the
plugin’s settings.

### What happens if I deactivate the plugin?

The blocking stops immediately and `.htaccess` rules are automatically cleaned up.
Your data (blocked IPs and whitelist) is preserved in case you reactivate the plugin
later.

### Is it safe for my .htaccess file?

Yes! The plugin uses unique markers (`# BEGIN EDH Bad Bots Block` / `# END EDH Bad
Bots Block`) to safely manage its rules without affecting other configurations. 
Rules are automatically removed on deactivation.

### Can I manually update hostnames for blocked IPs?

Yes! In the “Blocked Bots” tab, you can use the “Update Missing Hostnames” button
to resolve hostnames for IPs that don’t have them, or “Force Refresh All Hostnames”
to clear the cache and re-resolve all hostnames.

## Reviews

![](https://secure.gravatar.com/avatar/98a6682caa2182261a295b9c9fef872594ca8c6129a02002873300dbe0519a4c?
s=60&d=retro&r=g)

### 󠀁[Simple, does the job](https://wordpress.org/support/topic/simple-does-the-job-21/)󠁿

 [Aster](https://profiles.wordpress.org/asterselene/) Kerzu 24, 2025 1 reply

Interface is easy to understand, easy to access the list of blocked bots or add/
remove things to/from the whitelist. Even works if your site has a cache plugin,
since you can just add the trap link to exceptions.

 [ Read all 1 review ](https://wordpress.org/support/plugin/edh-bad-bots/reviews/)

## Contributors & Developers

“EDH Bad Bots” is open source software. The following people have contributed to
this plugin.

Contributors

 *   [ EncodeDotHost ](https://profiles.wordpress.org/encodedothost/)
 *   [ Neil Batchelor ](https://profiles.wordpress.org/nbwpuk/)

[Translate “EDH Bad Bots” into your language.](https://translate.wordpress.org/projects/wp-plugins/edh-bad-bots)

### Interested in development?

[Browse the code](https://plugins.trac.wordpress.org/browser/edh-bad-bots/), check
out the [SVN repository](https://plugins.svn.wordpress.org/edh-bad-bots/), or subscribe
to the [development log](https://plugins.trac.wordpress.org/log/edh-bad-bots/) by
[RSS](https://plugins.trac.wordpress.org/log/edh-bad-bots/?limit=100&mode=stop_on_copy&format=rss).

## Changelog

### Version 1.7.2

 * **Fix**: Replace `wp_redirect()` with `wp_safe_redirect()` across all admin form
   handlers
 * **Fix**: Replace `is_writable()` with `wp_is_writable()` for WP Filesystem API
   compliance
 * **Fix**: Escape block duration integer via `absint()` in help tab output to satisfy`
   OutputNotEscaped` sniff
 * **Fix**: Suppress `PrefixAllGlobals` sniff in admin view template (template-scoped
   variables, not true PHP globals)
 * **Update**: Tested up to WordPress 6.9

### Version 1.7.1

 * **Fix**: Removed `<Limit GET POST HEAD>` wrapper from `.htaccess` block rules—
   bots using other HTTP methods (DELETE, PUT, PATCH, etc.) are now blocked at the
   server level too
 * **Enhancement**: Background cron hostname resolution batch size increased from
   5 to 25 IPs per run, speeding up hostname population on sites with many blocked
   bots
 * **Performance**: `EDHBB_Admin` class is now only instantiated on admin requests(`
   is_admin()` guard), saving memory on every frontend page load
 * **Cleanup**: Plugin uninstall now removes all `_transient_edhbb_*` and `_transient_timeout_edhbb_*`
   entries from the options table for a fully clean uninstall

### Version 1.7.0

 * **Critical fix**: Database migrations now run on plugin updates, not just on 
   activation. A version-based check on `plugins_loaded` ensures schema changes (
   e.g. the hostname column) are applied even after automatic updates.
 * **Critical fix**: Removed synchronous `gethostbyaddr()`/`gethostbyname()` DNS
   calls from the frontend trap-hit path. These blocking OS calls could hang PHP
   workers under a botnet DoS. FCrDNS verification now runs exclusively in the background
   cron — verified legitimate crawlers are automatically unblocked and whitelisted
   by the cron job.
 * **Fix**: Replaced manual `preg_replace()`/`put_contents()` `.htaccess` rewrite
   with WordPress’s native `insert_with_markers()`, which uses `LOCK_EX` file locking
   to prevent `.htaccess` corruption under concurrent requests.
 * **Fix**: Added `uninstall.php` — custom database tables, plugin options, and 
   column-exists cache entries are now fully removed when the plugin is deleted 
   via WP Admin.
 * **Fix**: Unblocking an IP from a paginated admin list now returns the user to
   the same page instead of resetting to page 1.

### Version 1.6.0

 * **New**: FCrDNS (Forward-Confirmed Reverse DNS) verification on trap hits — verified
   Googlebot, Bingbot, and other legitimate crawlers are protected from being accidentally
   blocked. Extensible via the `edhbb_trusted_crawler_domains` filter hook.
 * **Fix**: Plugin deactivation now correctly removes `.htaccess` block rules, matching
   the documented behaviour. Previously, blocks persisted at the server level after
   deactivation.
 * **Fix**: Cron scheduling moved into the activation hook — removed a redundant`
   wp_next_scheduled()` check that ran on every single page load.
 * **Fix**: Force-refresh hostname cache now uses `delete_transient()` per IP instead
   of a direct SQL `DELETE` query, ensuring compatibility with object caches (Redis,
   Memcached) used by managed WordPress hosts.
 * **Enhancement**: Blocked bots admin list is now paginated (50 per page) to prevent
   browser crashes and PHP out-of-memory errors on sites with large numbers of blocked
   IPs.

### Version 1.5.0

 * **Security**: Fixed IP spoofing vulnerability — `get_client_ip()` now uses only`
   REMOTE_ADDR`, ignoring spoofable `HTTP_CLIENT_IP` and `HTTP_X_FORWARDED_FOR` 
   headers
 * **Security**: Fixed trap detection false positives — URL path is now compared
   strictly rather than using loose `strpos` matching, preventing query strings 
   from triggering blocks
 * **Performance**: Eliminated N+1 database queries during `.htaccess` generation—
   whitelist is now fetched once and checked with `in_array()` instead of a query
   per blocked IP
 * **Performance**: `init_filesystem()` no longer runs on every frontend page load—
   filesystem is only initialised when `.htaccess` write operations are actually
   needed
 * **Performance**: `is_ip_whitelisted()` and `is_bot_blocked()` now cache results
   in transients, with targeted cache invalidation on add/remove
 * **Performance**: `column_exists()` result is now cached in a WordPress option,
   eliminating repeated `INFORMATION_SCHEMA` queries
 * **Performance**: `clean_old_blocked_bots()` is now gated by an hourly transient,
   preventing a DELETE query on every page request
 * **Performance**: Removed synchronous DNS lookup on trap hit — bot is blocked 
   immediately and hostname is resolved by the background cron job
 * **Performance**: Force-refresh-all-hostnames capped at 50 IPs per run to prevent
   PHP timeout and memory limit issues on large datasets
 * **Fix**: Removed `[No PTR Record]` from the cron retry query — IPs with no PTR
   record are no longer retried on every hourly run
 * **Fix**: Removed broken `traditional_hostname_lookup()` fallback which passed
   a raw IP to a PTR lookup (always returned empty)
 * **Fix**: Replaced all `ReflectionClass` usage with direct `EDHBB_DNSLookup::get_hostname_for_blocked_ip()`
   calls
 * **Fix**: `.htaccess` marker patterns now wrapped in `preg_quote()` for correctness
 * **Fix**: Reduced verbose DNS debug logging — routine start/end messages removed;
   only error and fallback messages remain
 * **Accessibility**: Added `aria-hidden="true"` to the hidden trap link so screen
   readers ignore it

### Version 1.4.3

 * **New**: Advanced DNS lookup system with DNS over HTTPS (DoH) support
 * **New**: PTR record resolution for hostname identification of blocked IPs
 * **New**: Background hostname resolution via WordPress cron jobs
 * **New**: Manual hostname update buttons in admin interface
 * **New**: Force refresh all hostnames feature with cache clearing
 * **New**: Configurable block duration (days) in Options tab
 * **New**: Enhanced admin interface with hostname display in blocked bots table
 * **New**: Debug information panel for hostname resolution troubleshooting
 * **New**: Support for both IPv4 and IPv6 PTR lookups
 * **Enhancement**: Improved blocked bots table with hostname column
 * **Enhancement**: Better identification of blocked bots through hostname resolution
 * **Enhancement**: Automatic database migration system for hostname column
 * **Enhancement**: Fallback DNS resolution methods for better compatibility
 * **Enhancement**: DNS query caching for improved performance
 * **Fix**: Updated queries to gracefully handle missing columns during migration
 * **Fix**: Added backward compatibility for existing installations
 * **Fix**: Improved error handling and logging for database migrations

### Version 1.4.2

 * Fixed Internal.LineEndings.Mixed in class-edhbb-blocker.php

### Version 1.4.1

 * Fixed blank admin page

### Version 1.4.0

 * Refactored all class names to use the `EDHBB_` prefix to prevent conflicts.
 * Updated the “Tested up to” WordPress version to 6.8.
 * Corrected the “Requires PHP” version to 7.4 for consistency.

### Version 1.3.0

 * Bringing up to WordPress coding standards

### Version 1.2.3

 * Added instructions to the “Help” tab for excluding the unique trap URL from caching
   plugins.

### Version 1.2.2

 * **Fix**: Block duration is now a configurable setting

### Version 1.2.1

 * **Fix**: Fixing apache error doc

### Version 1.2.0

 * **New**: Added custom error page

### Version 1.1.2

 * **Fix**: Now adding htaccess rule at top of file

### Version 1.1.1

 * **Fix**: Trigger htaccess rules to have higher priority

### Version 1.1.0 – Major Feature Release

 * **New**: Server-level IP blocking via `.htaccess` file management
 * **New**: “Options” tab in admin interface for configurable blocking methods
 * **Enhanced**: Dual-level blocking system (server + PHP) for maximum effectiveness
 * **Added**: Automatic `.htaccess` file management with unique markers
 * **Added**: Smart whitelist filtering for `.htaccess` rules
 * **Improved**: Admin interface with enhanced tabbed navigation
 * **Enhanced**: Performance optimization with server-level blocking
 * **Added**: Nginx compatibility with PHP-only blocking fallback
 * **Updated**: Comprehensive documentation including `.htaccess` functionality
 * **Added**: Better error handling and logging for `.htaccess` operations
 * **Added**: Automatic cleanup of `.htaccess` rules on deactivation

### Version 1.0.4

 * Adding min PHP + WordPress requirements, tested on WordPress 6.8.2

### Version 1.0.3

 * Updated README and license

### Version 1.0.2

 * Added plugin action links for easier access to settings

### Version 1.0.1

 * Changed author name

### Version 1.0.0

 * Initial plugin release
 * Core bot detection and blocking functionality
 * Admin interface for managing whitelisted IPs and blocked bots
 * Automatic robots.txt integration

## Meta

 *  Version **1.7.2**
 *  Last updated **6 days ago**
 *  Active installations **20+**
 *  WordPress version ** 6.2 or higher **
 *  Tested up to **6.9.4**
 *  PHP version ** 7.4 or higher **
 *  Language
 * [English (US)](https://wordpress.org/plugins/edh-bad-bots/)
 * Tags
 * [bots](https://bre.wordpress.org/plugins/tags/bots/)[dns](https://bre.wordpress.org/plugins/tags/dns/)
   [hostname](https://bre.wordpress.org/plugins/tags/hostname/)[security](https://bre.wordpress.org/plugins/tags/security/)
 *  [Advanced View](https://bre.wordpress.org/plugins/edh-bad-bots/advanced/)

## Ratings

 5 out of 5 stars.

 *  [  1 5-star review     ](https://wordpress.org/support/plugin/edh-bad-bots/reviews/?filter=5)
 *  [  0 4-star reviews     ](https://wordpress.org/support/plugin/edh-bad-bots/reviews/?filter=4)
 *  [  0 3-star reviews     ](https://wordpress.org/support/plugin/edh-bad-bots/reviews/?filter=3)
 *  [  0 2-star reviews     ](https://wordpress.org/support/plugin/edh-bad-bots/reviews/?filter=2)
 *  [  0 1-star reviews     ](https://wordpress.org/support/plugin/edh-bad-bots/reviews/?filter=1)

[Your review](https://wordpress.org/support/plugin/edh-bad-bots/reviews/#new-post)

[See all reviews](https://wordpress.org/support/plugin/edh-bad-bots/reviews/)

## Contributors

 *   [ EncodeDotHost ](https://profiles.wordpress.org/encodedothost/)
 *   [ Neil Batchelor ](https://profiles.wordpress.org/nbwpuk/)

## Support

Got something to say? Need help?

 [View support forum](https://wordpress.org/support/plugin/edh-bad-bots/)