Technical
Typing like a person: rhythm, errors and corrections
August 1, 2026 · 7 min read
Swipes get scrutinised because they are visible. Typing gets a fixed delay between characters and no further thought — which is odd, because typing produces far more data points per action than any gesture does.
What constant-interval typing looks like
The default in most automation is to send characters at a fixed rate. Sixty milliseconds, sixty, sixty. A twenty-character string produces nineteen identical intervals.
Nothing about human typing works that way. Inter-keystroke intervals vary by an order of magnitude within a single word, and the variation is not random — it has structure that is well documented, because keystroke dynamics have been studied for decades as a biometric.
The structure worth knowing
Digraph timing
The gap between two keystrokes depends on which two keys. Letter pairs you type constantly — th, er, in — come out fast because they are motor patterns rather than individual decisions. Pairs that need the same finger to move twice, or an awkward stretch, take noticeably longer.
Reproducing full digraph tables is overkill for most purposes. The useful takeaway is simpler: intervals should vary per character pair, not be drawn independently from one distribution.
Word boundaries
People pause at the ends of words more than inside them, and pause longer before words they had to think about. A password typed from memory has a very different profile from a sentence being composed.
The long tail
Most intervals cluster in a narrow band. A few are enormous — someone looked away, checked a message, reconsidered a word. A distribution with a fat tail models this far better than uniform jitter around a mean.
This is the same shape that shows up in the gaps between actions, and for the same reason: attention is not uniform.
Cheapest meaningful change: stop drawing every interval from the same narrow range. A mixture — mostly short intervals, occasionally a much longer one — is closer to real than any amount of fine-tuning around a constant.
Errors, and why they are optional
Real typing contains mistakes and corrections. Backspaces, retyped characters, occasionally a word deleted and rewritten.
Simulating this is tempting and mostly not worth it. Two reasons.
First, errors interact badly with correctness. A flow that mistypes a login and corrects it has introduced a failure mode for a cosmetic gain. If the correction logic is wrong, or the field autocompletes mid-error, you have broken the flow to look more natural.
Second, plenty of real input has no errors in it. Short strings, autofilled values, anything typed carefully. Error-free typing is not itself suspicious.
If you do model errors, keep them to longer free-text entry, keep the rate low, and make the correction immediate — people notice a typo within a character or two, not five words later.
The iOS-specific part
Typing on a phone is not typing on a keyboard, and several things only exist on mobile.
The keyboard has to be up. Text goes in through the real iOS keyboard, which means it has to appear first — and it does not always appear when you expect. A flow that types into a field before the keyboard is ready loses characters.
Fields fight back. Phone numbers reformat as you type. Card fields insert spaces. Some fields switch layout mid-entry — a numeric pad appearing where a letter keyboard was. Automation that assumes the field will accept what it sends, unchanged, breaks on all of these.
Autocorrect and predictive text. iOS may substitute a word you did not type. For free text this is realistic and harmless. For a username or a password it is a silent corruption, and the flow proceeds happily with the wrong value.
Layout changes cost time. Switching from letters to numbers to symbols takes a person a visible moment. Sending those characters at the same rate as adjacent letters is one of the clearer tells in mobile typing.
What actually matters, ranked
| Property | Naive | Better | Worth it? |
|---|---|---|---|
| Interval distribution | Constant | Long-tailed mixture | Yes — cheap, large effect |
| Keyboard readiness | Type immediately | Wait for the keyboard | Yes — correctness, not realism |
| Layout switch cost | Same rate throughout | Extra time at switches | Yes — clear tell, easy fix |
| Verify what landed | Assume it worked | Read the field back | Yes — catches autocorrect |
| Word-boundary pauses | Uniform | Longer at boundaries | Moderate |
| Digraph-specific timing | One distribution | Per-pair | Diminishing returns |
| Errors and corrections | None | Occasional, immediate | Usually not — risk exceeds gain |
Notice that two of the highest-value items are about correctness rather than realism. Waiting for the keyboard and reading back what landed will save you more runs than any timing model — and a flow that silently typed the wrong thing is worse than one that obviously failed.
Smart typing
This is why Icemoon has a distinct smart typing action rather than a single "type text" primitive: the awkward cases — keyboard readiness, reformatting fields, numeric layouts, verifying what actually landed — are handled as part of the action instead of being your problem to discover one broken flow at a time.
The timing model underneath uses the same principle as the gesture layer: generate fresh from a distribution rather than replaying a constant.
Typing that goes through the real keyboard
Icemoon drives stock iPhones from your Mac — real touch events, the device's own keyboard, and gestures generated fresh every time. No jailbreak.
Start free trial