FCaptcha v1.3: Keystroke Cadence & Playwright Detection
FCaptcha v1.3 adds 7 biometric keystroke metrics, Playwright detection, AI agent bypass fixes, and server-side PoW validation.
WebDecoy Team
WebDecoy Security Team
FCaptcha v1.3: Keystroke Cadence Biometrics & Playwright Detection
FCaptcha v1.3 represents the biggest detection upgrade since the initial release. Three releases — v1.2.0, v1.2.1, and v1.3.0 — landed in rapid succession, each closing gaps that real-world bot operators were exploiting.
The headline: FCaptcha now analyzes how you type, not just how you move your mouse. Seven statistical metrics examine keystroke timing to catch bots that add timing jitter to appear human. Combined with new Playwright-specific detection and a patched AI agent bypass, FCaptcha v1.3 pushes the detection signal count past 50.
GitHub: github.com/webdecoy/fcaptcha Demo: webdecoy.com/product/fcaptcha-demo
What Changed and Why
The Problem: Bots Got Smarter
After FCaptcha’s initial release, we observed three bypass patterns in the wild:
Zero-movement clicks — AI agents like Manus were clicking the checkbox without generating any mouse movement. Because all behavioral checks required minimum trajectory lengths to trigger, zero-movement interactions slipped through silently.
Playwright stealth — Playwright’s stealth plugins delete
navigator.webdriverand suppress standard automation flags. Existing WebDriver detection missed these configurations entirely.Timing jitter bots — Sophisticated bots were adding random delays between keystrokes to mimic human typing rhythm. FCaptcha’s existing form analysis only checked average typing speed, which jitter bots passed easily.
Each release addressed one of these gaps.
v1.2.0: AI Agent Bypass Fix
The most critical fix. AI agents were bypassing FCaptcha by programmatically clicking the checkbox with zero mouse trajectory. The scoring logic required minimum mouse data to trigger — so no mouse data meant no penalty.
What Changed
Zero mouse movement is now flagged as a high-confidence bot signal:
- Zero trajectory (< 5 points, < 10px) with no touch or keyboard events: score penalty of 0.35
- Insufficient trajectory (< 10 points, < 30px): score penalty of 0.15
- Missing approach trajectory to the click target: score penalty of 0.7
Accessibility Exemptions
Touch users and keyboard-only users are explicitly exempt from mouse-movement checks:
- Touch users — Mobile taps don’t generate mouse events, so touch interactions (
touchEvents > 0) bypass mouse-movement scoring - Keyboard-only users — Tab+Enter navigation is valid accessibility behavior and is detected via keyboard events with zero mouse points
A touchstart listener was also added to the checkbox widget, which previously only listened for touchmove and missed simple taps.
v1.2.1: Playwright Detection & PoW Hardening
Playwright-Specific Detection
A new _detectPlaywright() method in the client-side EnvironmentalCollector checks for:
__pw*/__playwright*globals — Playwright injects these window properties during automation- Deleted
navigator.webdriver— Playwright stealth deletes the webdriver property from the Navigator prototype. Real browsers always have it defined. - Configurable
navigator.webdriver— If the property descriptor showsconfigurable: true, it has been tampered with - Missing
chrome.runtime— Chrome-based browsers always exposechrome.runtime. Playwright with Chromium often lacks it.
Server-side scoring weights these signals heavily:
| Signal | Score |
|---|---|
playwright_globals | 0.95 |
webdriver_deleted | 0.80 |
webdriver_configurable | 0.70 |
chrome_runtime_missing | 0.60 |
Server-Side PoW Timing Validation
Previously, proof-of-work timing was measured client-side only — easily spoofable. v1.2.1 adds server-side elapsed time measurement. If the server calculates that the PoW was solved in under 1,500ms (impossibly fast for the given difficulty), the result is flagged.
Additionally, PoW is now mandatory. A missing PoW solution triggers a hard-fail with score 0.9 and confidence 0.95, up from the previous lenient 0.5-0.6 penalty.
Tightened Accessibility Exemptions
The original accessibility exemptions were too permissive:
- Touch events required:
>= 3(was> 0) - Keyboard events required:
>= 2(was> 0)
A single synthetic touchstart or keydown event no longer bypasses behavioral analysis.
v1.3.0: Keystroke Cadence Analysis
The largest feature addition. FCaptcha now performs deep statistical analysis of keystroke timing patterns through seven biometric metrics.
Why Keystroke Timing Matters
Existing form analysis checked average typing speed and interval variance — two metrics that jitter bots defeat by adding Math.random() * delay between keystrokes. Real human typing has far more complex statistical properties that are hard to simulate:
- Dwell times vary based on finger strength, key position, and word familiarity
- Key rollovers (pressing the next key before releasing the current one) occur naturally in fast typists
- Burst patterns emerge as typists pause to think between phrases
- Sequential correlations mean the interval after pressing ‘T’ influences the interval before pressing ‘H’
The 7 Biometric Metrics
1. Dwell Variance Measures consistency in how long keys are held down. Humans show natural variation in dwell times based on finger mechanics. Bots using dispatchEvent or sendKeys produce unnaturally consistent dwell durations.
2. Log-Normal Fit Applies a Kolmogorov-Smirnov test to compare the distribution of inter-keystroke intervals against the expected human log-normal distribution. Human typing intervals follow a log-normal curve; synthetic intervals tend toward uniform or normal distributions.
3. Uniformity Detection Specifically catches Math.random()-based jitter. When bots add random delays using uniform random number generators, the interval distribution is detectable as uniform rather than log-normal.
4. Lag-1 Autocorrelation Evaluates sequential timing dependencies. In human typing, the time between keystroke N and N+1 correlates with the time between N+1 and N+2 — your typing rhythm carries momentum. Bots with independent random delays show near-zero autocorrelation.
5. Burst Regularity Analyzes variation in the pauses between typing bursts. Humans type in bursts separated by irregular thinking pauses. Bots tend to type at a steady pace or with artificially regular pause intervals.
6. Shannon Entropy Quantifies the information content within the interval distribution. Human typing produces moderate entropy — neither perfectly ordered nor perfectly random. Bots producing uniform random intervals show high entropy; bots with fixed intervals show low entropy.
7. Rollover Rate Detects overlapping keypresses where one key is pressed before the previous key is released. This is common in fast human typists but rare in automation frameworks that send discrete key events sequentially.
False Positive Prevention
Keystroke cadence analysis is gated conservatively:
- Minimum data threshold: Requires 20+ keystrokes and 15+ intervals before analysis activates
- Composite scoring: Multiple metrics must agree before flagging (composite
botScore > 0.55) - Scaled contribution: Cadence scores are multiplied by 0.7 to prevent dominating the overall detection score
- Diverse typing support: Slow typists, hunt-and-peck users, fast touch typists, and keyboard-only navigation all pass safely
Client-Side Changes
The FormAnalyzer class now tracks additional keystroke data per textarea:
- Dwell times — Duration each key is held down (keydown to keyup)
- Rollover events — When a new keydown fires while another key is still held
- Raw intervals — Full keystroke interval history (ring buffer, capped at 100)
Modifier keys (Shift, Control, Alt, Meta, CapsLock) are excluded from dwell and rollover tracking to avoid skewing biometric measurements.
Server-Side Changes
All three server implementations (Node.js, Python, Go) received:
- Statistical utility functions for variance, K-S testing, and entropy calculation
- A new
analyzeKeystrokeCadence()function called fromanalyzeFormInteraction() - 4 new test cases covering human cadence, constant-timing bots, alternating-jitter bots, and minimal data handling
Detection Weight Rebalancing
The overall scoring weights were rebalanced across releases:
| Category | v1.1 | v1.3 |
|---|---|---|
| Behavioral | 40% | 35% |
| Environmental | 35% | 30% |
| Temporal | 15% | 15% |
| Form & Keystroke | 10% | 20% |
The increased weight on form and keystroke signals reflects their improved accuracy after the cadence analysis addition.
What This Means for Bot Operators
Three common bypass strategies are now closed:
- “Click without moving” — Zero-movement interactions are flagged at 0.35+ score penalty
- “Use Playwright stealth” — Playwright globals, deleted webdriver, and missing chrome.runtime are all detected
- “Add random delays to typing” — Uniform random jitter is caught by log-normal fit, uniformity detection, and autocorrelation analysis
The combination of mandatory PoW with server-side timing, 50+ behavioral signals, and biometric keystroke analysis makes FCaptcha significantly harder to bypass at scale.
Getting Started
FCaptcha is fully open source and self-hosted. No external dependencies, no data sharing.
Quick Integration
<div id="captcha"></div>
<script src="/fcaptcha.js"></script>
<script>
FCaptcha.render('captcha', {
siteKey: 'your-site-key',
callback: (token) => {
fetch('/api/verify', {
method: 'POST',
body: JSON.stringify({ token })
});
}
});
</script>Server Implementations
Choose your backend:
- Go:
server-go/— High-performance, production-ready - Python:
server-python/— Flask-based, easy to customize - Node.js:
server-node/— Express-based, JavaScript ecosystem
All three implementations include the full detection pipeline: behavioral scoring, environmental analysis, PoW verification, and keystroke cadence analysis.
Try the Demo
See FCaptcha in action on our interactive demo page. Test both checkbox and invisible modes with real-time scoring.
What’s Next
FCaptcha development continues in the open. Planned areas of investigation include:
- Mouse dynamics biometrics — Extending the cadence analysis approach to mouse movement patterns
- Cross-session fingerprint correlation — Detecting when the same bot framework is used across sessions
- Adaptive difficulty — Dynamically adjusting PoW difficulty based on real-time threat signals
Follow development on GitHub or try FCaptcha on your own infrastructure.
Share this post
Like this post? Share it with your friends!
Want to see WebDecoy in action?
Get a personalized demo from our team.