The same type twice
never twiceTwo opposite twists cancel out. Each type is used at most once; rotation about x, y, or z counts as one type.
Turn the wheels until the jelly fits inside the gold outline. Learn it in four short levels; each one adds a wheel. These are real challenges, but here the dots show you where to go.
Each wheel bends space before the shape is evaluated. Here are the building blocks, rendered live on one fixed shape. In the formulas, y is a secret axis, a is how far the wheel is from its neutral point, and the shader applies the inverse map.
How much these move a point depends on where the point is: a twist turns the ends more than the middle, and a bulge swells only the waist. No single matrix describes the result, so the picture changes in ways a solver can't summarise with a few numbers. That makes them harder to model, and it also makes the shape behave like jelly.
Rendering the transformations…
These keep straight lines straight and move every point by the same rule: rotate, shift, shear, or stretch. A wheel's whole effect is then one small matrix. After a couple of pictures a solver can fit that matrix and predict every other position, for example by tracking the silhouette's centre and orientation. They are easy for people too, so each level has one as an anchor (two on Hard): Easy combines one linear and one non-linear wheel, Normal one and two, Hard two and two.
Every wheel runs from 0 to 1 and starts in the middle. It has two secret values: the solution, and a neutral point. Its distance from the neutral point drives one main transformation and up to two weaker ones. Neutral points are random, so the target is a random pose, not a plain shape.
Each transformation type appears at most once per challenge. Two twists, say, could cancel each other out, which is confusing to reason about.
Every axis, sign, and phase is random. But some transformations look so alike that, on a shared axis, one wheel could partly undo or imitate another. That makes the puzzle confusing rather than hard, so the server never builds these:
Two opposite twists cancel out. Each type is used at most once; rotation about x, y, or z counts as one type.
All three change how wide the slices are across the axis, so a bulge would read as a partial stretch.
All three push slices sideways depending on where they sit along the axis. Part of a bend looks like a shear.
Both turn slices around an axis. Combined, on any axis, they are too hard to tell apart.
Translation has no axis, so it combines with everything. The width and sideways groups have at most three members each, one per axis, so a valid choice always exists.
When a challenge is created, the server turns each wheel ⅛ of its travel both ways from the solution and measures how much the silhouette changes. It scales the wheel's strength until that change lands in the sensitivity band (default 0.08–0.2). A transformation that can't get there, such as a twist of an almost round shape, is replaced. So no wheel is uselessly subtle or twitchy.
Each picture costs a one-use ticket, replaced with every answer, so a replayed request never buys an extra view. The server allows a sustained frame rate, 12 per second by default: about where separate pictures start to read as motion. The page always sends the latest wheel values.
Optionally, each ticket also needs a proof of work, a SHA-256 chain computed in the background. It is off by default, because making the ~100 pictures a person needs more expensive adds little security.
Each picture's silhouette is compared with the target's by intersection over union, and the score comes back with the picture to fill the bar. Showing it costs nothing: a bot could segment the picture and compute it anyway.
The moment the score reaches the required overlap, the wheels lock, the outline turns green, and the server renders the solved jelly once more at double resolution. If you get stuck, Show solution turns the wheels to the answer; asking before you solve ends that challenge.
The jelly is a signed distance field: a function that gives each point's distance to the surface. Two to four spheres and rounded boxes are blended smoothly. A WGSL compute shader on the GPU marches a ray per pixel along that distance, then shades the result as glossy, slightly translucent jelly in a small coloured room.
With the Rust server, the browser never receives the shape, only pictures. Rendering in the browser would hand the shape to a bot.
The public demo is a static site, so there the very same Rust backend runs in your browser, compiled to WebAssembly and rendering with WebGL2. That makes the shape inspectable: fine for trying it out, not for a real CAPTCHA.
All of these appear under Settings in the demo. Easy, Normal, and Hard are presets.
| Setting | Default | Meaning |
|---|
| Transformation | Range | Effect |
|---|
This is a research prototype. Nobody has shown yet that humans beat automated solvers here. Numerical search and inverse rendering are plausible attacks. A production service would also need redeemable completion proofs, quotas, and an accessible alternative.