How a CS2 jump-throw actually works: a 297 ms latch window, not an apex snap
A CS2 jump-throw latches your aim, eye position and velocity exactly 0.1 s after the jump, and it accepts a release from 6 ticks before the jump to 12 ticks after it — a 297 ms tolerance — so the grenade always inherits the same 218.86838 u/s of upward velocity. The popular explanation, that the game forces the release at peak height, is wrong in both directions: the latch fires well before the apex, and it is a fixed-time snapshot rather than a height test. That is why a hand-timed jump-throw lands identically without a bind, and it is the byte-level meaning of the community's "200 ms perfect window".
Transcribed from the current CS2 server binary (build 1.41.6.8/10847) with every constant byte-verified in the raw listing, and reconciled against real jump-throws recorded in current-build demos.
Latch time
jump instant + 0.100 s
Release tolerance
~297 ms (6 ticks before to 12 ticks after the jump)
Pulling the pin does not throw the grenade. Releasing the attack button schedules a throw for 0.1 s later — and because both the current time and the scheduled time are tick-quantized, that delay is exactly seven ticks. The grenade is constructed then, and the throw reads the player pose at that moment, not at the moment you released.
Separately, a fresh grounded jump schedules a pose latch for the jump instant plus 0.1 s. When that time arrives the game snapshots the live eye angles, eye position and velocity, sub-tick exact. When the throw constructor later asks for a throw source it returns that cached pose instead of the live one — provided the snapshot is at most 0.2 s old.
The tolerance falls out of that arithmetic, and it is much wider than the folklore: the latched pose is used for every release from 6 ticks before the jump to 12 ticks after it, regardless of sub-tick phase. Pressing jump and attack in the same instant sits in the middle of the window, which is why the manual jump-throw is so reliable.
Early releases are rescued by an explicit mechanism rather than by luck. The constructor asks a look-ahead predicate whether the window will still be valid when it fires; if it will, and the throw has not already been deferred, the game pushes construction back another 0.1 s and returns without throwing. One shot, and its purpose is to move a too-early throw into the window.
The number the grenade inherits is then determined, not chosen. The latch happens 0.1 s after the jump, and on the byte-verified velocity ladder takeoff is 298.86838 u/s, so the latched value is 298.86838 − 800 × 0.1 = 218.86838. Three real jump-throws in a current-build demo invert to 218.658, 218.888 and 218.888 — two bit-identical. That is not a rung on the per-tick velocity ladder (223.868 and 211.368 are the neighbours) and it is nowhere near the apex, which is zero and about 0.358 s away. The measurement refutes the apex story on its own.
A crouch-jump throw latches 3.1252 u/s higher, against a predicted 0.5 × 800/128 = 3.1250, pooled over 24 crouched throws — and the crouched cluster is tighter than the standing one, which means a deterministic branch rather than spread.
Where the release lands, as ticks relative to the jump (x = release tick − jump tick − sub-tick phase)
x ≤ −13.4
live pose, no latch
−13.4 < x ≤ −7.6
deferred, then live pose
−7.6 < x ≤ −0.6
deferred, then LATCHED
−0.6 < x ≤ 12.2
LATCHED
12.2 < x ≤ 12.8
live pose at release + 7
x > 12.8
live pose, no latch
Every fact on this page, with its tier
The jump-throw latch: the pose is snapshotted at the jump instant + 0.1 s and used by the throw constructor while the snapshot is at most 0.2 s old, giving a latched release band of x ∈ (−7.6, 12.2] ticks
Value
~297 ms tolerance
Confidence tier
TRANSCRIBED (T3) BYTE-VERIFIED
How it was derived
Function identities anchored by RTTI and vtable slots rather than guessed; every constant read out of the raw instruction listing, because the decompiler folds away float arguments passed in registers.
Evidence
Window 0.2 s, latch and constructor delay 0.1 s, tick interval 1/64 and the 1.25 inheritance are all byte-verified constants. The tolerance table is arithmetic on them; its browser realization is gate-verified over 59 releases spanning x = −6 to +12, all inheriting 218.86838 with zero spread, 22 of them through the deferral.
Latched vertical velocity = 218.86838 u/s (takeoff 298.86838 minus one tenth of a second of 800 u/s² gravity)
Value
218.86838 u/s
Confidence tier
DEMO-VERIFIED (Δ 0.02 u/s)
How it was derived
Predicted from the byte-verified jump ladder, then recovered from three real jump-throws by inverting the native throw law on the server-latched launch velocity.
Evidence
Measured 218.658 / 218.888 / 218.888; two bit-identical. Not a ladder rung (neighbours 223.868 and 211.368) and not the apex.
Jump end-of-tick cached vz = 286.36838, then −12.5 per tick (the 301.99338 jump impulse is the PRE-gravity value; CS2 applies the jump-tick gravity)
Value
286.36838 u/s
Confidence tier
MEASURED (live lab 2026-07-21) — supersedes an INDICATIVE 301.993377
How it was derived
Read from the networked pawn velocity in a live lab on the current build, for clean stamina-free non-ducking standing jumps.
Evidence
Deterministic 6/6 across two runs; grounded velocity 0; effective initial 298.868 gives a feet apex of 55.82 u. The older position-differenced "304.09" was half a step out of phase and blind to the cached value.
A crouch-jump throw latches exactly 0.5 · sv_gravity/128 higher than a standing one
Value
+3.1250 u/s
Confidence tier
DEMO-DERIVED 2026-07-24 (mechanism OPEN)
How it was derived
Recovered from the server's own latched launch velocity — no position differencing — by inverting the native throw law, on three maps independently.
Evidence
Pooled standing median 218.7905 (n = 265) vs crouched 221.9157 (n = 24), difference 3.1252 against a predicted 3.1250. The crouched cluster is tighter than the standing one, so it is a branch and not spread.
Open questions — what is not known
Why the crouch-jump offset exists is not established.
Either CS2 skips a half-substep gravity term for a ducked jump — which would also raise the crouch-jump apex — or the latch samples 1/256 s earlier, which would not. Discriminating needs a clean takeoff velocity, and duck hull re-centring moves the recorded feet origin during exactly the ticks that measurement needs. The offset is therefore applied where it was measured, at the latch, and not at the jump impulse.
A command-backlog correction term is transcribed but unidentified.
The release handler subtracts a term built from two tick fields that have not been identified. For a single local command stream it is zero, and that is how it is treated — untested against a networked capture.
The per-jump spread is bounded by one demo only.
About ±0.2 u/s of variation between jumps comes from the sub-tick phase of the latch tick, and its bound comes from a single recording.
Last updated 2026-07-24 — the date of the measurement, not of this
page's rendering. What the confidence tiers mean. Memorin is not affiliated
with or endorsed by Valve; Counter-Strike 2 is a trademark of Valve Corporation.