The most realistic keyboard typing simulator based on Markov Chains
Project description
HumanTyping 🤖⌨️
The most realistic keyboard typing simulator based on Markov Chains and stochastic processes.
HumanTyping models authentic human typing behavior with unprecedented accuracy, making automated typing indistinguishable from real users.
🎬 See It In Action
Watch HumanTyping simulate realistic typing with natural speed variations, errors, and corrections.
⚡ Quick Start (Playwright)
# Install
pip install -e .[playwright]
from playwright.async_api import async_playwright
from humantyping import HumanTyper
import asyncio
async def main():
async with async_playwright() as p:
browser = await p.chromium.launch(headless=False)
page = await browser.new_page()
await page.goto("https://google.com")
typer = HumanTyper(wpm=70) # Create typer
search_box = page.locator("[name='q']")
await search_box.click()
await typer.type(search_box, "realistic typing!") # Type like a human!
await browser.close()
asyncio.run(main())
📚 See More Examples → | 🚀 Full Guide →
✨ Features
Advanced Typing Simulation
- Variable Speed: Common words typed 40% faster, complex words 30% slower
- Bigram Acceleration: Frequent letter pairs (th, er, in) typed in rapid bursts
- Fatigue Modeling: Typing speed gradually decreases over time (0.05% per character)
- Natural Pauses: Micro-pauses between words (250ms average)
Realistic Error Patterns
- Neighbor Errors: Types adjacent keys based on keyboard layout (QWERTY/AZERTY)
- Swap Errors: Character inversions like "teh" → "the"
- Delayed Detection: Some errors go unnoticed until final proofreading
- Correction Behavior: Uses Backspace immediately or navigates with arrow keys later
Customization
- Adjustable WPM (Words Per Minute) with natural variance
- Support for accents and special characters
- Uppercase detection (Shift key penalty)
- Configurable error rates and reaction times
🧠 How It Works
HumanTyping uses a semi-Markov process where:
- States represent typing progress (characters typed)
- Transitions model keystrokes with time and accuracy variations
- Error probability depends on:
- Word difficulty (common vs. rare)
- Key distance on the keyboard
- Character complexity (accents, uppercase)
The system maintains both a mental cursor (where the user thinks they are) and a physical cursor (actual position), allowing realistic proofreading and corrections.
📦 Installation
Option 1: Install from PyPI (Recommended) 🌟
Once published to PyPI:
# Basic installation
pip install humantyping
# With Playwright support
pip install humantyping[playwright]
# With Selenium support
pip install humantyping[selenium]
# With both
pip install humantyping[playwright,selenium]
Option 2: Install from GitHub Releases
# Install latest release
pip install https://github.com/Lax3n/HumanTyping/releases/latest/download/humantyping-1.0.0-py3-none-any.whl
Option 3: Install from Source (Development)
# Clone the repository
git clone https://github.com/Lax3n/HumanTyping.git
cd HumanTyping
# Install in editable mode
pip install -e .[playwright]
# Or with uv (recommended for development)
uv sync --extra playwright
Verify Installation
python -c "from humantyping import HumanTyper; print('✓ Installation successful!')"
🚀 Usage
Demo Mode (Visual Simulation)
Watch typing happen in real-time with errors and corrections:
uv run main.py "Hello world, this is a realistic typing test." --mode demo
Options:
--wpm <number>: Set target typing speed (default: 60)--mode demo: Real-time animation
Monte Carlo Mode (Statistical Analysis)
Generate statistics over multiple simulations:
uv run main.py "Performance test" --mode montecarlo --n 1000 --wpm 80
Output:
Running 1000 simulations for text: 'Performance test' (Target WPM: 80)
--- Monte Carlo Results ---
Estimated Mean Time : 3.2145 s
Standard Deviation : 0.4521 s
Min / Max : 2.1034 s / 5.8912 s
Computation Time : 2.1456 s
🤖 Integration with Automation Frameworks
Playwright (Async)
The easiest way to add realistic typing to your Playwright scripts:
import asyncio
from playwright.async_api import async_playwright
from humantyping import HumanTyper # Import from the package!
async def main():
async with async_playwright() as p:
browser = await p.chromium.launch(headless=False)
page = await browser.new_page()
await page.goto("https://example.com")
# Create typer with custom WPM
typer = HumanTyper(wpm=70)
# Type realistically into any input field
search_box = page.locator("input[name='search']")
await search_box.click()
await typer.type(search_box, "How to type like a human?")
await browser.close()
if __name__ == "__main__":
asyncio.run(main())
That's it! Just 3 lines of code:
- Import
HumanTyper - Create an instance:
typer = HumanTyper(wpm=70) - Type:
await typer.type(element, "your text")
Selenium & Appium (Sync)
from selenium import webdriver
from humantyping import HumanTyper
# For Selenium
driver = webdriver.Chrome()
driver.get("https://example.com")
human = HumanTyper(wpm=60)
search_box = driver.find_element("name", "search")
human.type_sync(search_box, "Typing with human-like behavior")
driver.quit()
# For Appium
# from appium import webdriver
# ... driver setup ...
# search_field = driver.find_element(by=AppiumBy.ACCESSIBILITY_ID, value='Search')
# human.type_sync(search_field, "Typing on mobile")
The integration module handles all typing events:
- Correct keystrokes
- Error keystrokes (wrong neighbors)
- Swap errors (character inversions)
- Backspace corrections
- Arrow key navigation (for late corrections)
🔧 Customization
Edit src/config.py to fine-tune the simulation:
# Typing speed
DEFAULT_WPM = 60 # Base speed
WPM_STD = 10 # Variance between sessions
# Error rates
PROB_ERROR = 0.04 # 4% chance of typing wrong key
PROB_SWAP_ERROR = 0.015 # 1.5% chance of swapping two characters
PROB_NOTICE_ERROR = 0.85 # 85% chance to notice errors immediately
# Speed adjustments
SPEED_BOOST_COMMON_WORD = 0.6 # Common words 40% faster
SPEED_BOOST_BIGRAM = 0.4 # Frequent bigrams 60% faster
SPEED_PENALTY_COMPLEX_WORD = 1.3 # Complex words 30% slower
# Timing (seconds)
TIME_SPACE_PAUSE_MEAN = 0.25 # Pause between words
TIME_BACKSPACE_MEAN = 0.12 # Backspace press time
TIME_ARROW_MEAN = 0.15 # Arrow key navigation time
TIME_REACTION_MEAN = 0.35 # "Oops" delay after error
# Fatigue
FATIGUE_FACTOR = 1.0005 # 0.05% slowdown per character
📂 Project Structure
HumanTyping/
├── src/
│ ├── config.py # All simulation parameters
│ ├── typer.py # Core Markov model and state machine
│ ├── keyboard.py # QWERTY/AZERTY layouts, key distances
│ ├── language.py # Word difficulty, common bigrams
│ ├── simulation.py # Demo and Monte Carlo runners
│ └── integration.py # Playwright/Selenium integration
├── main.py # CLI entry point
└── README.md
🤝 Contributing
Forks and contributions are very welcome!
Ideas for enhancements:
- Additional keyboard layouts (Dvorak, Colemak)
- Language-specific models (French, Spanish, etc.)
- Time-of-day fatigue patterns
- Muscle memory for repeated phrases
- Copy-paste detection avoidance
Open an issue or submit a PR!
📊 Example Output
uv run main.py "The quick brown fox jumps." --mode demo
--- Real-Time Simulation Demo: 'The quick brown fox jumps.' (Target WPM: 60.0) ---
Preparing simulation...
START TYPING:
----------------------------------------
The quick brown fox jumps.
----------------------------------------
Total Simulated Time: 6.2341s
Errors made and corrected: 1
🎯 Use Cases
- Browser Automation: Bypass typing detection systems
- Testing: Simulate realistic user input for QA
- Research: Study typing patterns and ergonomics
- Education: Demonstrate Markov processes and stochastic modeling
📜 License
MIT License - Feel free to use in your projects!
Built with ❤️ and probabilities by the open-source community.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file humantyping-1.0.3.tar.gz.
File metadata
- Download URL: humantyping-1.0.3.tar.gz
- Upload date:
- Size: 102.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
42aaaeca4a235b5093e9714970e0eceae91530e38df8369a18afe88623af28a4
|
|
| MD5 |
f31b7c92d3098c248ba41a346ae062f9
|
|
| BLAKE2b-256 |
3568aeb47ff2cb7abc5a92b648f741492f8fe49aa81843b758c1dff9d1fe3b11
|
Provenance
The following attestation bundles were made for humantyping-1.0.3.tar.gz:
Publisher:
publish.yml on Lax3n/HumanTyping
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
humantyping-1.0.3.tar.gz -
Subject digest:
42aaaeca4a235b5093e9714970e0eceae91530e38df8369a18afe88623af28a4 - Sigstore transparency entry: 1177069938
- Sigstore integration time:
-
Permalink:
Lax3n/HumanTyping@cc4cbb558455387f42d12c9e483e7add2043b438 -
Branch / Tag:
refs/tags/v1.0.3 - Owner: https://github.com/Lax3n
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@cc4cbb558455387f42d12c9e483e7add2043b438 -
Trigger Event:
release
-
Statement type:
File details
Details for the file humantyping-1.0.3-py3-none-any.whl.
File metadata
- Download URL: humantyping-1.0.3-py3-none-any.whl
- Upload date:
- Size: 16.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6707f2957f2d924378319b1cd49465ddd3dab17bb8ebf0be1ee9f7d8f5f7c444
|
|
| MD5 |
2bab96b3c6b8babb6594ce0654f55306
|
|
| BLAKE2b-256 |
9a27f8eb5852aeac2f122268eb2f9505da0c08b9d570cdbff775ffe6577a5a33
|
Provenance
The following attestation bundles were made for humantyping-1.0.3-py3-none-any.whl:
Publisher:
publish.yml on Lax3n/HumanTyping
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
humantyping-1.0.3-py3-none-any.whl -
Subject digest:
6707f2957f2d924378319b1cd49465ddd3dab17bb8ebf0be1ee9f7d8f5f7c444 - Sigstore transparency entry: 1177070251
- Sigstore integration time:
-
Permalink:
Lax3n/HumanTyping@cc4cbb558455387f42d12c9e483e7add2043b438 -
Branch / Tag:
refs/tags/v1.0.3 - Owner: https://github.com/Lax3n
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@cc4cbb558455387f42d12c9e483e7add2043b438 -
Trigger Event:
release
-
Statement type: