Troubleshooting
Most issues fall into one of a few buckets: keys wrong, caching plugin in the way, WP-Cron not firing, or a theme conflict. Start with the symptom that matches yours.
Widget Does Not Appear
Symptom: Form loads but no Turnstile widget
Checklist:
- Is the Site Key set on the API Settings tab? Empty = no widget
- Is the form ticked on its respective tab (WooCommerce / WordPress / WC Forms)?
- Do you have a caching plugin active? Flush cache + hard refresh
- Is your hostname in the Cloudflare widget's hostname list?
- Open browser DevTools → Console — any JS errors?
- Open DevTools → Network — does
challenges.cloudflare.com/turnstile/v0/api.jsload (200 OK)?
Caching Plugin Conflicts
| Plugin | Fix |
|---|---|
| WP Rocket | Settings → File Optimization → Exclude these URLs from JS concatenation: challenges.cloudflare.com. Also Settings → Cache → Exclude /my-account/, /checkout/ |
| LiteSpeed Cache | Page Optimization → JS Settings → Exclude from JS Combine: cloudflare, turnstile. Purge all |
| Autoptimize | Settings → JS Options → Exclude scripts: turnstile, cloudflare |
| W3 Total Cache | Performance → Minify → JS → Never minify URLs: challenges.cloudflare.com |
After changing any cache setting, hard-refresh (Ctrl+Shift+R).
Theme Hook Conflicts
If your theme is aggressively overriding login_form, woocommerce_login_form, or comment_form hooks, the widget may render at the wrong position or not at all.
Fix: edit the theme's form template to include:
<?php echo do_shortcode('[wkcft-turnstile]'); ?>
At the position you want.
Validation Always Fails
Symptom: "Please complete the security check" on every submit
Check:
- Secret Key correct on the API Settings tab? Use the show/hide toggle to re-verify
- Click Test Connection on the API Settings tab — any error there is your real problem
- Does your server have outbound HTTPS to
challenges.cloudflare.com? Test via SSH:
curl -X POST https://challenges.cloudflare.com/turnstile/v0/siteverify \
-d "secret=YOUR_SECRET&response=test"
If this times out or returns an error, your firewall is blocking the API — contact hosting.
Cloudflare Error Codes
The error code in the log tells you exactly what failed:
| Code | Meaning | Fix |
|---|---|---|
missing-input-secret | Secret Key field empty | Paste Secret Key, save |
invalid-input-secret | Secret Key is wrong | Re-copy from Cloudflare dashboard |
missing-input-response | Token not sent with form | Widget did not render — check Site Key + caching |
invalid-input-response | Token invalid / expired | Tokens expire in 5 min. Usually caching. Flush cache |
timeout-or-duplicate | Token reused or aged out | Full-page cache served the same token twice. Exclude form pages from cache |
prohibited-replay | Same token used twice | Same — caching issue |
bad-request | Malformed request to Cloudflare | Rare. Check curl works from your server |
WP-Cron Not Running
Symptom: Email digest / webhook never fire
WP-Cron only runs when someone visits your site. Low-traffic = missed crons.
Fix 1 — Add Real Server Cron
Crontab entry that hits WP-Cron every 5 min:
*/5 * * * * wget -q -O - https://yoursite.com/wp-cron.php?doing_wp_cron > /dev/null 2>&1
Add to wp-config.php to stop WordPress from running WP-Cron on every page load:
define('DISABLE_WP_CRON', true);
Fix 2 — Manually Trigger a Cron
Via WP-CLI:
wp cron event run wkcft_send_digest
wp cron event run wkcft_check_notifications
Or via a plugin like WP Crontrol (for non-CLI environments).
Verify Scheduled Hooks Exist
wp cron event list | grep wkcft
Should show:
wkcft_send_digest
wkcft_check_notifications
wkcft_logger_purge
Locked Out of wp-admin
Symptom: CAPTCHA is on wp-login, Cloudflare is down or widget won't load
Option 1 — Recovery URL:
https://yoursite.com/?wkcft_recovery=YOUR_TOKEN
Then log in normally.
Option 2 — Disable via database:
UPDATE wp_options SET option_value='no' WHERE option_name='wkcft_wp_login';
Or via WP-CLI:
wp option update wkcft_wp_login no
Option 3 — Deactivate plugin:
wp plugin deactivate turnstile-captcha-for-woocommerce
Widget in Wrong Position
Symptom: Widget shows above the form title or below the page footer
Theme-level hook interference.
Quick fix — use the shortcode at the right position:
- Turn OFF the auto-inject for that form (untick on settings tab)
- Edit the theme template that renders the form
- Insert
<?php echo do_shortcode('[wkcft-turnstile]'); ?>at the correct position - Save template
Logged-In User Still Sees CAPTCHA
Symptom: You turned on "Skip logged-in users" but widget still appears
Check:
- Conditions tab — is
skip_logged_inreally ticked? Save Changes? is_user_logged_in()returns false in your context? Some login issues show user as guest until refresh- IP blacklist — is your current IP on the blacklist? Blacklist overrides skip rules
- Clear any page cache
Multiple Widgets on Same Page
Symptom: Two widgets render on a page with shortcode + auto-inject
Fix: If you added a manual shortcode, remove either the shortcode OR the auto-inject toggle for that form. Pick one.
For legitimate multi-widget pages (shortcode used twice), pass different IDs:
[wkcft-turnstile id="widget-newsletter"]
[wkcft-turnstile id="widget-contact"]
Analytics Page Empty
Symptom: "No data available" even though you have run form submits
Check:
- Is logging enabled? Check filter
wkcft_log_enabled(default true) - Is the table created? Run:
SHOW TABLES LIKE 'wp_wkcft_log';
If missing, deactivate + reactivate the plugin (activation creates the table).
- Date range — is it too narrow? Switch to "All time"
- Object cache — some caching plugins serve stale analytics data. Wait 5 min or disable object cache for
wkcft_statsgroup
Rate-Limited By Mistake
Symptom: A real customer or your own IP got blocked
Fixes:
- Send them the Recovery URL
- Add their IP to the IP whitelist
- Wait out the lockout (default 5 min)
- SQL cleanup:
DELETE FROM wp_options WHERE option_name LIKE '_transient_wkcft_rl_%';
HTTPS Required
Symptom: Widget will not render on HTTP pages
Cloudflare Turnstile requires HTTPS. HTTP-only sites are not supported.
Fix: install an SSL certificate. Free option: Let's Encrypt via your host or Cloudflare's free SSL.
Order Placed Without CAPTCHA
Symptom: Orders are getting through without triggering CAPTCHA
Check:
- Is checkout enabled?
wkcft_block_checkoutshould beyes - Is the user on IP whitelist or country whitelist?
- Is warn-only mode on? Turn off on General tab
- Is the user logged in +
skip_logged_inon? Expected behavior
Check the analytics dashboard — if checkout submissions are NOT in the log, the validator is not being called. Compatibility issue with another plugin that overrides the checkout process.
Performance Issues
Symptom: Admin analytics page slow
Fix:
- Reduce log retention: filter
wkcft_log_retention_daysto 30 - Manually purge old rows:
DELETE FROM wp_wkcft_log WHERE created_at < DATE_SUB(NOW(), INTERVAL 30 DAY);
- Add covering indexes (already added by default — only needed if you wrote a custom query)
Symptom: Frontend pages slow
Fix:
- Switch Load Mode to
lazywith a 2-3s delay - Switch Appearance to
executefor silent verification - Exclude form pages from full-page cache (cached pages with stale tokens cause issues)
Translation Not Appearing
Symptom: Plugin text shows in English despite locale set to French/Spanish/German/Portuguese
Check:
- Site locale: Settings → General → Site Language set correctly
/wp-content/plugins/turnstile-captcha-for-woocommerce/languages/folder contains the right.mofile for your locale- WordPress locale:
get_locale()returns the expected code - Refresh object cache
Missing a language? Only de_DE, es_ES, fr_FR, pt_BR ship. For others, generate from the .pot template using Poedit or Loco Translate.
Still Stuck?
- FAQ — Quick answers
- Glossary — Plain-English definitions
- Webkul Support: webkul.uvdesk.com
- GitHub Issues (if public): the plugin's repo
