Veriprose is a free, browser-based essay editor that quietly records how a student writes — not just the final text — so you can have better-informed conversations about authorship and academic integrity.
As a student drafts in the editor, it captures typing rhythm, paste and drag-in events, periodic snapshots of the essay's growth, edit/correction patterns, and when the window was switched away from. On save it cryptographically signs the file so you can confirm it wasn't altered afterward.
You then open that file in this verifier, which recomputes the signature and surfaces plain-language consistency checks — flagging things like text pasted in wholesale, suspiciously fast or machine-even typing, or a long pause followed by a rapid catch-up burst — alongside charts and side-by-side revision diffs that let you watch the essay take shape.
Its value is in restoring visibility into the writing process: discouraging shortcuts, rewarding genuine drafting, and giving you concrete, reviewable evidence to ground an honest discussion when something looks off.
Veriprose is a deterrent and a conversation-starter, not a forensic verdict. Its signals are heuristic, never proof, and are designed to point you toward specific moments worth asking a student about rather than to "catch" anyone. — See the changelog for version history.
Veriprose records signals while a student writes — typing rhythm, paste events, revision history, edit-action counts. The verifier surfaces patterns that warrant a closer look. None of these are proof of cheating; they are prompts to investigate. Single signals have many innocent explanations. Combinations are much harder to dismiss. A valid signature confirms the file came from real Veriprose software and hasn't been altered since save — it does not vouch for the truthfulness of what the student did during the session. Note: Do not share the verifier link with students.
This top row aggregates the four signals below most directly tied to manual transcription of pre-written text (e.g., reading AI output from another window and typing it). It counts how many trip Warn status:
| Markers | Status | Reading |
|---|---|---|
| 0 | OK | Clean profile. |
| 1 | Info | Single signal could be many things; check the corresponding row. |
| 2+ | Warn | Correlated signals are characteristic of transcription. |
Computed as (totalCharsTyped / 5) / activeMinutes. The denominator is active session time — only seconds when the tab was visible and the student had recent activity (within 2 minutes). Leaving the tab open overnight does not deflate the rate. Pasted content is excluded; only what was actually typed counts. The 5-chars-per-word divisor is the standard WPM convention.
| Range | Status | Meaning |
|---|---|---|
< 2 WPM (over 10+ min) | Warn | Session time vastly exceeds output. |
8–25 WPM | OK | Typical sustained composition. |
25–50 WPM | OK | Skilled fast composition. |
> 50 WPM | Warn | Higher than most writers sustain over a full essay. |
> 80 WPM | Warn | Transcription speed; very unlikely for original composition. |
The row also surfaces a per-revision typed peak: walks adjacent revisions, computes typed-words-per-minute for each interval (subtracting paste contributions), reports the max. A session-average that looks fine but with one revision interval over 100 typed-WPM suggests reading and transcribing a paragraph at a time.
False positives: Skilled fast typists — programmers, journalists, ESL students translating mentally — can sometimes sustain 40–50 WPM in composition. Read alongside other signals.
Number of inter-keystroke timing samples recorded (capped at the 200 most recent). If a student typed substantially (>200 chars) but timings are nearly empty (<20), suggests scripted input that bypassed the keydown event — or an unsupported browser.
False positives: IME composition (Chinese/Japanese/Korean input methods) does not always fire individual keydown events. Students using IME may legitimately show low timing counts.
Auto-save fires every 60 seconds while typing. The check examines adjacent revisions and flags:
Note: A long pause followed by a burst of typing can produce a large jump without being suspicious. Cross-reference with the per-revision typed peak in the Writing pace row, which subtracts pastes and reports the actual typing rate.
The coefficient of variation (CV) of inter-keystroke intervals: standard deviation divided by mean. Human typing is bursty — fingers click in flurries with thinking pauses between, producing CV well above 0.5. Macros and replay scripts produce uniform intervals, with CV near zero. CV < 0.30 trips Warn.
False positives and limits: A short-burst typist with no thinking pauses can have low CV without being a script. Conversely, a determined attacker can tune their generator's intervals to widen CV deliberately. This signal is fakable, which is why it lives in a panel of many rather than as a verdict.
Counts keydown events with isTrusted=false — events dispatched by JavaScript (userscripts, dispatchEvent calls) rather than physical keys. Hardware keyboards always produce isTrusted=true. Any non-zero count is strong evidence of automated input.
Important caveat: Two paths can produce trusted events while still automating input. (a) DevTools-Protocol-based automation (Puppeteer, Playwright, Selenium with appropriate flags) generates events at the browser level with isTrusted=true. (b) Hardware macro keys — programmable peripherals like Logitech G Hub, Razer Synapse, or Corsair iCUE can bind a single physical key to "type out this entire passage." Because the keystrokes come through the OS HID driver, they look identical to physical typing here. The Typing rhythm check sometimes catches uniform-interval macros, but a sophisticated macro can vary the intervals deliberately. Zero synthetic events is necessary but not sufficient for authenticity.
The editor records a timeline of window-level blur/focus events — every time the whole window loses or regains OS focus (alt-tab, switching apps or displays). This is distinct from the idle accounting used elsewhere. The pattern that warrants a closer look is a long blur followed immediately by a fast typing burst on return — what you'd expect if text is being read from another window or a printout and typed back. A WARN means at least one long absence (≥20s) was followed by a ≥50 WPM burst; INFO means there were long absences but no catch-up burst.
Limits: Stepping away mid-session is completely normal, and a second monitor never triggers a window blur at all (focus stays on the editor's window). Treat this strictly as a pointer to specific revision diffs to read, not as a verdict. Files saved by builds before v1.4.6 have no focus timeline and show "n/a".
What fraction of editing actions were corrections (Backspace, Delete, Cut) versus character insertions. Composing writers self-correct constantly. Pure transcribers don't reach back — they read source text and type it forward.
| Range | Status | Reading |
|---|---|---|
< 2% | Warn | No self-correction; transcription pattern. |
2–5% | Info | Below typical range for composition. |
5–25% | OK | Healthy composition (5–15% expected). |
> 25% | Info | Heavy editor (not suspicious, just unusual). |
Combined-signal escalation: a ratio in the 2–5% range becomes Warn when typing pace is also elevated (>40 WPM). "Few backspaces with slow careful typing" has innocent explanations; "few backspaces and fast typing" really only matches transcription — it's hard to type fast without errors while composing original prose.
Field availability: Recorded by editor v1.4.2 and later (backspaceCount + cutCount in the saved JSON). Older files show n/a.
Counts revision intervals where the word count went down — sentence rewrites, deletions, paragraph reshuffling. Genuine composition almost always produces some negative-delta intervals scattered through the session. Pure forward growth across many revisions is consistent with linear transcription.
| Pattern | Status | Reading |
|---|---|---|
| Zero negative-delta intervals | Warn | Monotonic growth; transcription pattern. |
| All decreases in final quarter, count ≤ cleanup threshold | Warn | "Transcribe linearly, then clean up at end." |
| All decreases in final quarter, count above threshold | Info | Heavy late-edit phase (legitimate pattern). |
| < 5% decrease rate, scattered | Info | Low rate; clean composer or partial transcription. |
| Healthy mix scattered through session | OK | Iterative composition. |
The cleanup-pattern threshold scales with revision count: max(1, floor(N/15)). Allows roughly one cleanup edit per 15 revisions before the cleanup-only pattern stops matching — a 60-revision session with 4 late edits trips the warning, but with 8 late edits would not (that's a heavy late-edit phase, not a cleanup signature).
The note also surfaces which revisions contained the decreases (e.g., "rev 34/34" or "revs 32, 34/40"). Numbering matches the verifier's Revisions tab below so you can verify the claim by clicking through.
A sticky taint that flips on if the editor loaded a .essay file whose signature failed verification. Once tainted, the flag persists through every subsequent save — even if the student continues writing and re-exports, the verifier still sees it. When this row fires, the audit trail before that load cannot be trusted.
This row only appears when the flag is set. A clean session never shows it.
Files saved by Veriprose v1.4.7 or later carry a complete, timestamped record of every edit — insertions, deletions, pastes, undos. Two things are built on it:
The Edit history check row replays that record and verifies it reproduces the submitted essay (whitespace-insensitive, since formatting boundaries differ between the record and the rendered text). A match is strong evidence the essay was produced by exactly the recorded session; a mismatch means the history has a gap or the text was altered outside it. Older files simply read n/a.
The Replay tab plays the record like a screen recording of the document: watch the essay being written at ×5–×100 speed, scrub to any moment, and follow the playhead on the Session timeline chart. Composition looks like thinking — backtracking, rewriting, sentences dying mid-thought. Transcription looks like a printer. Long idle pauses are compressed (the clock shows true session time), and typed vs. pasted material lands exactly as it did during the session.
The Replay tab's Origin view button swaps the playback for the final text shaded by where each character came from: typed (unshaded), pasted or dragged, carried over from a loaded/recovered file, undo/redo, or automated change. Because the record is per-edit, the shading survives partial rewrites — retype a pasted sentence yourself and only the words you actually typed lose the paste shading. The edit-history record also sharpens the timeline's typed-pace strip to ~30-second resolution.
Replay shows how the text arrived, not why. A clean linear run can be a well-rehearsed opening paragraph; watch enough of the session to see the pattern, and treat what you see as the start of a conversation.
The first chart overlays the session's events on the word-count curve so the whole story reads in one glance. Red-ringed dots mark paste events at the moment they landed, sized by how much text arrived. Gray vertical bands mark stretches of 20+ seconds where the editor window lost focus. The strip under the time axis colors each revision interval by its typed pace — green ≤50 WPM, amber 50–80, red >80 — the same thresholds as the Writing pace check, so the strip and the checks list always agree.
Useful shapes: a long gray band followed by a red strip segment and a steep climb is the "read elsewhere, then type fast" profile; a paste ring sitting exactly where the curve jumps confirms what the jump was; scattered short gray bands with normal pace are ordinary source-checking. Files saved before v1.4.6 carry no focus data and simply show no bands.
Like every signal here, the timeline is context for a conversation, not a verdict — a gray band can be a student checking sources, and one fast interval can be a well-rehearsed sentence.
Veriprose is a deterrent, not a forensic tool. The HMAC signature uses a client-side key, which a determined adversary can extract from the source. The signals raise the cost of cheating and surface obvious cases; they do not prove anything on their own. Treat Warn rows as conversation starters with the student, not verdicts. — See the changelog for version history.
.essay file onto the drop zone below. The tool will verify and display it automatically..essay files onto Batch Review below to scan them in one pass.Verification needs the .essay file — the student's PDF is the readable copy, and carries the signature so you can tell which .essay it belongs to, but cannot be verified on its own.
Drop a whole folder's worth of .essay files to scan them at once. Every file runs the same checks as a single review; the table sorts so outliers cluster at the top. Click any row to open that submission in full.
Relative signals are within this batch only — a pace or warning count that stands out from peers is a prompt to look closer, not a verdict. Click a column header to sort; click a row to open it.