EDH Bad Bots – WordPress plugin | WordPress.org
Skip to content
Plugin Directory
EDH Bad Bots
Details
Reviews
Installation
Development
Support
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:
Trap URL Generation
: Creates a unique, hidden URL specific to your domain
Robots.txt Integration
: Automatically adds a
Disallow
rule for the trap URL
Hidden Link Placement
: Places an invisible link to the trap URL in your site’s footer
Bot Detection
: When bad bots ignore robots.txt and follow the hidden link, they’re identified
Automatic Blocking
: Detected bot IPs are blocked with configurable duration and immediate effect
Hostname Resolution
: PTR record lookups identify the hostname/organization behind blocked IPs
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
Clone the repository to your WordPress plugins directory
Ensure you have a WordPress development environment running
Activate the plugin and test your changes
License
This project is licensed under the GPL v3 or later.
Author
EncodeDotHost
– Website:
– GitHub:
@EncodeDotHost
Contributors
@nbwpuk
Support
For support, please visit
or create an issue on the GitHub repository.
Screenshots
Allow list management
Block list management with hostname display
Options Page with configurable settings
Installation
Upload the
edh-bad-bots
folder to your
/wp-content/plugins/
directory
Activate the plugin through the ‘Plugins’ menu in WordPress
The plugin works immediately – no configuration required!
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
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
Contributors & Developers
“EDH Bad Bots” is open source software. The following people have contributed to this plugin.
Contributors
EncodeDotHost
Neil Batchelor
Translate “EDH Bad Bots” into your language.
Interested in development?
Browse the code
, check out the
SVN repository
, or subscribe to the
development log
by
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

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
: 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
2 weeks
ago
Active installations
20+
WordPress version
6.2 or higher
Tested up to
6.9.4
PHP version
7.4 or higher
Tags
bots
dns
hostname
security
Advanced View
Ratings
out of 5 stars.
1 5-star review
5 stars
0 4-star reviews
4 stars
0 3-star reviews
3 stars
0 2-star reviews
2 stars
0 1-star reviews
1 star
Your review
See all
reviews
Contributors
EncodeDotHost
Neil Batchelor
Support
Got something to say? Need help?
View support forum