ClickFix — Clipboard-write Mechanisms Test Page

One section per technique that real ClickFix campaigns use to get a command onto the clipboard. Each test writes the same inert canary payload, then reads the clipboard back to show what landed. The pill on each test indicates whether the technique fires a copy/cut DOM event that an event-based detector can observe.

Clipboard inspector

After any test, the readout below shows what is on the clipboard right now. Empty clipboard means the detector intercepted and cleared the copy. The payload appearing verbatim means the technique was not caught.

No reads yet.

Async Clipboard API

1. navigator.clipboard.writeText() no copy event

The dominant pattern in modern fake-CAPTCHA / “Verify you are human” lures. Triggered from a button’s click handler; the user gesture is the button click itself, so no permission prompt fires. No DOM selection, no copy event.

navigator.clipboard.writeText(PAYLOAD)
Not run.

2. navigator.clipboard.write() with single-format ClipboardItem no copy event

Same delivery vector, richer API. Seen in newer kits that want to set non-text formats. Single text/plain blob here, same payload.

navigator.clipboard.write([
  new ClipboardItem({ 'text/plain': new Blob([PAYLOAD], { type: 'text/plain' }) })
])
Not run.

3. navigator.clipboard.write() with multi-format ClipboardItem (HTML decoy + plain payload) no copy event

Used by kits that try to fool clipboard managers / preview tooling that display HTML: the visible HTML form is innocuous (e.g. a verification code), the text/plain form is the command. Terminal pastes always take plain text.

navigator.clipboard.write([
  new ClipboardItem({
    'text/plain': new Blob([PAYLOAD], { type: 'text/plain' }),
    'text/html':  new Blob(['<b>Verification code: 4F7-2A1</b>'], { type: 'text/html' })
  })
])
Not run.

Legacy synchronous API (document.execCommand)

4. Hidden <textarea> + execCommand('copy') fires copy event

The pre-navigator.clipboard standard technique. Still ubiquitous because many ClickFix kits were written when it was canonical, and because it works as an automatic fallback when the async API is blocked. Programmatic selection of an off-screen <textarea>, then document.execCommand('copy').

const ta = document.createElement('textarea');
ta.value = PAYLOAD;
ta.style.position = 'fixed'; ta.style.opacity = '0';
document.body.appendChild(ta);
ta.select();
document.execCommand('copy');
ta.remove();
Not run.

5. Range-based programmatic selection of a hidden <div> + execCommand('copy') fires copy event

Variant of #4 that selects via Range + Selection instead of a form element. Used by some kits to avoid focus-stealing on mobile or to copy from an existing visible node.

const div = document.createElement('div');
div.textContent = PAYLOAD;
div.style.position = 'fixed'; div.style.left = '-9999px';
document.body.appendChild(div);
const range = document.createRange();
range.selectNodeContents(div);
const sel = window.getSelection();
sel.removeAllRanges(); sel.addRange(range);
document.execCommand('copy');
sel.removeAllRanges();
div.remove();
Not run.

6. contenteditable + execCommand('cut') fires cut event

Less common but in the wild. Same delivery, but uses cut on a contenteditable region. Detectors that only listen to copy and not cut miss this.

const div = document.createElement('div');
div.contentEditable = 'true';
div.textContent = PAYLOAD;
div.style.position = 'fixed'; div.style.opacity = '0';
document.body.appendChild(div);
const range = document.createRange();
range.selectNodeContents(div);
const sel = window.getSelection();
sel.removeAllRanges(); sel.addRange(range);
document.execCommand('cut');
div.remove();
Not run.

Hijacking a real user copy

7. Swap clipboardData during the user’s copy event fires copy event

The page lets the user select visible, benign text (a “verification code”, an order number, a wallet address) and registers a copy listener that replaces the clipboard payload with the command. The detector that reads document.getSelection() sees the benign text and approves; the clipboard receives the command. Common against crypto wallets / bank account fields; used by some ClickFix variants too.

Select the text inside the dashed box, then press Ctrl/+C:

Verification code: 4F7-2A1-9KQ
Not armed.

8. oncopy attribute / inline handler (variant of #7) fires copy event

Same idea as #7 but the hijack is attached as an inline DOM attribute on the source element rather than a addEventListener call. Selecting and copying the box below replaces the clipboard with the payload. Some content scripts that only look at addEventListener-attached listeners (e.g. via debug APIs) miss this; behaviourally it’s identical.

Order #: ORD-2026-001
Select the box above and copy it.

Drag and drop / paste-from-button

9. DataTransfer on dragstart fires dragstart, not copy

A few lures instruct users to “drag this verification token into the Run dialog” (which doesn’t actually accept drops, but the same UI works on terminal apps and chat windows). The data is set on the DataTransfer object of a dragstart event — no copy event ever fires, so clipboard-event detectors don’t see it.

Drag the chip below to a text field to see the payload appear:

☰ verify-me
Drag the chip above into any text field.
Detection coverage cheat-sheet