Getting Started
Choose the right plan
Must-Have Captcha is an intelligent form protection plugin based on real human interactions. There are 2 available plans:
Single plan
You can use Must-Have Captcha with the Single plan for 1 WordPress site. It's perfect if you have a single site or want to test the plugin's capabilities.
Unlimited plan
We created the Unlimited plan for freelancers and agencies who manage multiple sites. This plan can be used on unlimited sites, perfect for protecting forms across all your WordPress installations.
Install Must-Have Captcha
- Login to My account on musthaveplugins.com
- Download the Must-Have Captcha installer from the Must-Have Captcha box
- Login to your WordPress admin where you would like to install Must-Have Captcha
- Go to Plugins > Add new and click to upload plugin
- Select the downloaded ZIP file (must-have-captcha.zip) and click to install
- Activate the plugin - it works immediately with default settings
Configuration
Must-Have Captcha works automatically after installation with no configuration required. However, you can fine-tune the protection to suit your site's needs from the plugin settings page in WordPress admin.
Protection Level
Choose how strict the plugin should be when blocking suspicious submissions by adjusting the threshold setting:
- Basic: Basic bot protection without affecting legitimate users, best for personal blogs and low-traffic websites
- Normal: Balanced protection that blocks most automated attacks, ideal for business websites and community sites
- Strict: Maximum protection against sophisticated bots and spam, recommended for e-commerce sites and websites with high spam traffic
Logged In Users
When enabled, the plugin will skip captcha validation for logged-in users. This is useful for sites where users have already been verified through the registration process. Use this setting to provide a smoother experience for your registered users while maintaining protection for anonymous visitors.
Expiry
Determine how long to keep blocked requests in the database for review. Options range from 1 day to keeping forever:
- 1 day: Minimal storage period, saves database space but gives less time to review blocked submissions
- 1 week: Short-term storage that works for most sites to review blocked requests
- 1 month: Standard setting for sites with moderate traffic that need more time to review
- 1 year: Long-term storage for thorough analysis of blocked submissions
- Keep forever: Never delete blocked requests, maximum ability to review all blocked submissions
Longer expiry periods give administrators more time to review and potentially recover legitimate submissions that were incorrectly blocked.
Custom 403 Page
When enabled, you can select a WordPress page to display when submissions are blocked. This allows you to create a more informative and user-friendly experience when spam or bot submissions are detected, perhaps explaining why they were blocked or providing alternative contact methods.
Custom Rules
Create custom protection rules to whitelist specific URLs or IP addresses:
- Type: URL or IP address
- Value: The URL pattern or IP address (supports CIDR notation for IP ranges)
- Protection Level: How strictly to apply protection to this rule
- Note: Optional information to remember why you created the rule
Protection Levels for Custom Rules
When creating custom rules, you can choose from these protection levels:
- Never Block: Always allow requests, regardless of suspicion level (whitelist)
- Basic: Block only highly suspicious requests
- Normal: Apply balanced protection
- Strict: Maximum protection against bots
- Block & Ignore: Always block but don't store in the blocked requests database
- No Logging: Use the global protection level but do not log blocked requests
Blocked Requests
The Blocked Requests dashboard shows all submissions that have been blocked by the plugin. For each blocked request, you can view:
- URL: The page where the submission was attempted
- Type: The form type that was blocked (comment, contact form, etc.)
- IP: The visitor's IP address
- Score: The trustability score assigned (and why it was too low)
- User Agent: Information about the browser and device used
- Date: When the submission was blocked
- Form Data: The actual content of the blocked submission
- Request Headers: HTTP headers sent with the submission request
You can filter, sort, and search through blocked requests to identify patterns of spam attacks or find legitimate submissions that were incorrectly blocked.
Replaying Blocked Requests
One of Must-Have Captcha's unique features is the ability to replay blocked submissions that were mistakenly flagged as spam:
- Go to the Blocked Requests tab in the plugin dashboard
- Click "View Details" on any blocked submission
- Review the submission content to ensure it's legitimate
- Click "Accept" to process the submission as if it was just submitted
This feature ensures you never lose legitimate form submissions due to false positives, particularly useful for contact forms, orders, or registrations from real users who might have triggered protection rules.
Note: Requests containing masked sensitive data (like passwords, credit card numbers, etc.) cannot be replayed because sensitive data is not stored for security reasons.
Available Filters
Customize Must-Have Captcha's behavior using these developer hooks:
mhcaptcha/threshold
Modify the captcha threshold for specific pages, post types, or conditions:
// Modify the captcha threshold based on page context
add_filter('mhcaptcha/threshold', function($threshold) {
if (defined('DOING_AJAX') && $_POST['action'] == 'my-whitelisted-ajax-action'){
return 15; // Basic protection for whitelisted AJAX action
}
return $threshold; // Default for everything else
});
mhcaptcha/score
Fine-tune the scoring system for specific user groups or contexts:
// Customize captcha scoring logic
add_filter('mhcaptcha/score', function($score, $cookie_value) {
// Add points for specific countries by Cloudflare country id
if (isset($_SERVER['HTTP_CF_IPCOUNTRY']) && $_SERVER['HTTP_CF_IPCOUNTRY'] == 'DE') {
$score += 10; // Add points for visitors from trusted countries
}
return $score;
}, 10, 2);
mhcaptcha/is_trustable_request
Bypass captcha checks for specific request types:
// Bypass captcha for specific scenarios
add_filter('mhcaptcha/is_trustable_request', function($is_trustable) {
// Skip captcha for specific form submissions
if (isset($_POST['form_id']) && $_POST['form_id'] === 'internal_form') {
return true; // Mark as trustable, bypassing checks
}
return $is_trustable; // Default behavior for other requests
});
mhcaptcha/store_blocked_request
Control whether blocked requests should be stored in the database:
// Prevent storing certain blocked requests
add_filter('mhcaptcha/store_blocked_request', function($store_request) {
// Don't store blocked requests from specific URLs
if (strpos($_SERVER['REQUEST_URI'], '/high-volume-form/') !== false) {
return false; // Don't store these blocked requests
}
return $store_request; // Default behavior for other requests
});
mhcaptcha/blocked_status_header
Customize the HTTP status code sent when a request is blocked:
// Change the HTTP status code for blocked requests
add_filter('mhcaptcha/blocked_status_header', function($status_code) {
// Use 429 (Too Many Requests) instead of 403 (Forbidden)
return 429;
});
mhcaptcha/default_score
Modify the default score assigned to requests:
// Change the default score
add_filter('mhcaptcha/default_score', function($default_score) {
// Set a more lenient default score
return 15;
});
mhcaptcha/cloud_rules
Customize the cloud rules used for IP-based filtering:
// Modify cloud rules
add_filter('mhcaptcha/cloud_rules', function($rules) {
// Add custom IPs to the whitelist
if (!isset($rules['whitelist'])) {
$rules['whitelist'] = array();
}
// Add your office IP range to whitelist
$rules['whitelist'][] = '203.0.113.0/24';
return $rules;
});
mhcaptcha/get_template
Customize the HTML templates used by the plugin:
// Add a custom message to the blocked template
add_filter('mhcaptcha/get_template', function($template_html, $template_name) {
// Only modify the blocked template
if ($template_name === 'blocked') {
// Simply add a message at the end of the template
$template_html .= '<div class="custom-message">If you believe this is an error, please contact us.</div>';
}
return $template_html;
}, 10, 2);
mhcaptcha/get_svg
Customize SVG icons used in the plugin interface:
// Customize SVG icons
add_filter('mhcaptcha/get_svg', function($svg, $file) {
// Replace the lock icon with a custom version
if ($file === 'lock') {
return '<svg><!-- Your custom SVG code here --></svg>';
}
return $svg;
}, 10, 2);
mhcaptcha/request_type
Customize how request types are detected and categorized:
// Customize request type detection
add_filter('mhcaptcha/request_type', function($type, $post_data, $url, $headers) {
// Identify a custom form submission
if (isset($post_data['my_custom_form_id'])) {
return 'custom_form';
}
return $type;
}, 10, 4);
mhcaptcha/api_request_args
Customize API request arguments when communicating with the Must-Have Captcha API:
// Customize API request arguments
add_filter('mhcaptcha/api_request_args', function($args) {
// Increase timeout for API requests
$args['timeout'] = 30;
return $args;
});
mhcaptcha/sensitive_input_patterns
Define patterns for sensitive data that should be masked in stored requests:
// Add custom sensitive data patterns
add_filter('mhcaptcha/sensitive_input_patterns', function($patterns) {
// Add pattern for custom sensitive field
$patterns[] = '/ssn\d*|social.*security/i';
return $patterns;
});
mhcaptcha/custom_rules
Programmatically add or modify custom rules:
// Add custom rules programmatically
add_filter('mhcaptcha/custom_rules', function($rules) {
// Add a rule to whitelist specific API endpoint
$rules[] = array(
'type' => 'url',
'value' => '/wp-json/custom-api/',
'protection' => 'none', // No protection for this endpoint
'order' => 5, // High priority
'note' => 'API Whitelist - Added programmatically'
);
return $rules;
});
Available Actions
Must-Have Captcha provides action hooks that you can use to extend functionality:
mhcaptcha/send_daily_summary
This action is triggered when the daily summary report is scheduled to be sent. You can hook into this to perform additional tasks when summaries are generated:
// Hook into the daily summary generation
add_action('mhcaptcha/send_daily_summary', function() {
// Perform additional tasks when daily summaries are sent
// For example, log summary generation to a custom log
error_log('Must-Have Captcha daily summary generated at ' . date('Y-m-d H:i:s'));
});
mhcaptcha/send_weekly_summary
Similar to the daily summary action, but triggered for weekly summary reports:
// Hook into the weekly summary generation
add_action('mhcaptcha/send_weekly_summary', function() {
// Perform additional tasks when weekly summaries are sent
});
mhcaptcha/send_monthly_summary
Triggered when monthly summary reports are generated:
// Hook into the monthly summary generation
add_action('mhcaptcha/send_monthly_summary', function() {
// Perform additional tasks when monthly summaries are sent
});
mhcaptcha/uninstall
This action runs during the plugin uninstallation process. You can hook into it to clean up any custom data or settings you've added:
// Clean up custom data during uninstallation
add_action('mhcaptcha/uninstall', function() {
// Remove any custom options or database entries you've created
delete_option('my_custom_mhcaptcha_setting');
});
Compatibility Features
Must-Have Captcha includes several compatibility features to ensure it works well with other plugins and server environments:
WordPress Loopback Request Detection
The plugin automatically detects and allows WordPress loopback requests (when WordPress makes HTTP requests to itself). This prevents the plugin from blocking important internal WordPress functionality like:
- Site Health checks
- Auto-updates
- Post previews
- REST API internal calls
This is handled by adding a special header to all WordPress HTTP requests and checking for this header when processing incoming requests.
Cross-Server Headers Compatibility
Must-Have Captcha includes a custom implementation of get_all_headers()
that works reliably across different server environments, including:
- Apache with mod_php
- Nginx with PHP-FPM
- CGI/FastCGI environments
- Various hosting configurations
This ensures consistent behavior regardless of your server setup.
Must-Have Cookie Compatibility
If you're also using the Must-Have Cookie plugin for GDPR/cookie compliance, Must-Have Captcha automatically registers its cookies as "essential" so they continue to function even when a visitor hasn't accepted cookies. This ensures your forms remain protected while complying with privacy regulations.
Changelog
0.1.5 – 2025.05.13.
Improve auto whitelist
0.1.4 – 2025.05.06.
Minor bugfixes
0.1.3 – 2025.04.25.
Initial public beta release