> ## Documentation Index
> Fetch the complete documentation index at: https://docs.verifyyou.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Overview

> One single-use code per human, good exactly once.

## One password per person

Anything you hand out on a link can be forwarded, shared, and taken twice. A survey, a giveaway, a beta invite, an event registration, a claim form. The link cannot tell a real first-timer from the same person on a second browser.

It bites hardest in market research and academic panels. Bots, duplicate respondents, professional survey-takers and survey farms clear a simple screener and land in your data, so you pay for completes that are not real and clean it up afterward. HumanCheck moves the check upstream, before your first question, so only a real, unique, present human ever reaches it.

One idea holds the whole thing up: **every password is tied to one unique human and works exactly once.**

<div>
  <div className="vy-car-wrap vy-car-narrow mt-8">
    <div className="vy-st-row">
      <button id="st1" className="vy-st vy-on" onClick={() => { for (const el of document.querySelectorAll('.vy-car-slide')) el.setAttribute('data-pos', String((parseInt(el.id.slice(2), 10) - 1 + 3) % 3)); for (const el of document.querySelectorAll('.vy-st')) el.classList.remove('vy-on'); document.getElementById('st1').classList.add('vy-on'); }}><span className="vy-num">1</span><span className="vy-st-label">A passcode per human</span></button>
      <button id="st2" className="vy-st" onClick={() => { for (const el of document.querySelectorAll('.vy-car-slide')) el.setAttribute('data-pos', String((parseInt(el.id.slice(2), 10) - 2 + 3) % 3)); for (const el of document.querySelectorAll('.vy-st')) el.classList.remove('vy-on'); document.getElementById('st2').classList.add('vy-on'); }}><span className="vy-num">2</span><span className="vy-st-label">Fakes locked out</span></button>
      <button id="st3" className="vy-st" onClick={() => { for (const el of document.querySelectorAll('.vy-car-slide')) el.setAttribute('data-pos', String((parseInt(el.id.slice(2), 10) - 3 + 3) % 3)); for (const el of document.querySelectorAll('.vy-st')) el.classList.remove('vy-on'); document.getElementById('st3').classList.add('vy-on'); }}><span className="vy-num">3</span><span className="vy-st-label">Clean data</span></button>
    </div>

    <div className="vy-car">
      <div className="vy-car-glow" />

      <div id="sl1" className="vy-car-slide" data-pos="0">
        <span className="vy-num vy-car-num">1</span>
        <p className="vy-sp-text text-gray-900 dark:text-zinc-50">Each verified person receives a one-time passcode, created for their face alone and dropped onto their link. It fills itself in when they arrive.</p>

        <div className="vy-viz">
          <div className="vy-viz-head"><span className="vy-viz-headico"><Icon icon="lock" iconType="light" size={13} /></span>One-time passcode</div>
          <div className="vy-viz-field"><span className="vy-viz-code">vyp\_k2•••••••4qt</span><span className="vy-viz-check"><Icon icon="circle-check" iconType="light" size={16} /></span></div>
          <div className="vy-viz-sub">Filled in from their link. Works exactly once.</div>
        </div>
      </div>

      <div id="sl2" className="vy-car-slide" data-pos="1">
        <span className="vy-num vy-car-num">2</span>
        <p className="vy-sp-text text-gray-900 dark:text-zinc-50">A bot never earns a passcode, because it cannot pass a live face check. The same face never earns a second one. And each passcode works exactly once, so a forwarded or shared one is already spent.</p>

        <div className="vy-viz">
          <div className="vy-viz-lane">
            <span className="vy-viz-ico">
              <Icon icon="user" iconType="light" size={17} />
            </span>

            <svg className="vy-viz-arrow" viewBox="0 0 64 16" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
              <path d="M2 8 h52" stroke="currentColor" strokeWidth="1.5" />

              <path d="M48 3 L56 8 L48 13" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
            </svg>

            <span className="vy-viz-out vy-viz-pass"><span className="vy-viz-outico"><Icon icon="check" iconType="light" size={13} /></span>Through</span>
          </div>

          <div className="vy-viz-lane">
            <span className="vy-viz-ico">
              <Icon icon="robot" iconType="light" size={17} />
            </span>

            <svg className="vy-viz-arrow" viewBox="0 0 64 16" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
              <path d="M2 8 h38" stroke="currentColor" strokeWidth="1.5" />

              <path d="M46 2 v12" stroke="currentColor" strokeWidth="2" strokeLinecap="round" />
            </svg>

            <span className="vy-viz-out vy-viz-fail"><span className="vy-viz-outico"><Icon icon="xmark" iconType="light" size={13} /></span>Blocked</span>
          </div>

          <div className="vy-viz-lane">
            <span className="vy-viz-ico">
              <Icon icon="user-group" iconType="light" size={17} />
            </span>

            <svg className="vy-viz-arrow" viewBox="0 0 64 16" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
              <path d="M2 8 h38" stroke="currentColor" strokeWidth="1.5" />

              <path d="M46 2 v12" stroke="currentColor" strokeWidth="2" strokeLinecap="round" />
            </svg>

            <span className="vy-viz-out vy-viz-fail"><span className="vy-viz-outico"><Icon icon="xmark" iconType="light" size={13} /></span>Same face, second try</span>
          </div>
        </div>
      </div>

      <div id="sl3" className="vy-car-slide" data-pos="2">
        <span className="vy-num vy-car-num">3</span>
        <p className="vy-sp-text text-gray-900 dark:text-zinc-50">Only real, first-time people get through. Everyone else stops at the check, so there is nothing to clean up afterwards.</p>

        <div className="vy-viz">
          <div className="vy-viz-row"><span className="vy-viz-id">rsp\_78421</span><span className="vy-viz-tag">Verified</span></div>
          <div className="vy-viz-row"><span className="vy-viz-id">rsp\_78422</span><span className="vy-viz-tag">Blocked</span><span className="vy-viz-pill vy-viz-no"><Icon icon="xmark" iconType="light" size={11} /></span></div>
          <div className="vy-viz-row"><span className="vy-viz-id">rsp\_78424</span><span className="vy-viz-tag">Verified</span></div>
        </div>
      </div>

      <div className="vy-car-prog">
        <span id="vyprog" />
      </div>
    </div>

    <div className="vy-car-nav">
      <img src="https://mintcdn.com/verifyyou/KqaO94oxL_imvB_J/logo/light.svg?fit=max&auto=format&n=KqaO94oxL_imvB_J&q=85&s=4aff6ab29a2ef5b68d92718687870caa" alt="" style={{ display: 'none' }} onLoad={() => { if (window.__vyAuto) return; window.__vyAuto = true; if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return; let prog = 0; let paused = false; document.addEventListener('pointerover', (e) => { const inCar = e.target && e.target.closest && e.target.closest('.vy-car'); if (inCar && !paused) { paused = true; const b = document.getElementById('vyprog'); if (b) b.style.opacity = '0.35'; } else if (!inCar && paused) { paused = false; const b = document.getElementById('vyprog'); if (b) b.style.opacity = '1'; } }); document.addEventListener('click', (e) => { if (e.target && e.target.closest && e.target.closest('.vy-car-arrow, .vy-st')) prog = 0; }, true); setInterval(() => { const bar = document.getElementById('vyprog'); if (!bar) return; if (paused || document.hidden) return; prog += 50 / 7000; if (prog >= 1) { prog = 0; const btns = document.querySelectorAll('.vy-car-arrow'); if (btns[1]) btns[1].click(); } bar.style.width = String(Math.min(prog * 100, 100)) + '%'; }, 50); }} data-og-width="199" width="199" data-og-height="44" height="44" data-path="logo/light.svg" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/verifyyou/KqaO94oxL_imvB_J/logo/light.svg?w=280&fit=max&auto=format&n=KqaO94oxL_imvB_J&q=85&s=8439788be14d042b8aac4a74e6210e8b 280w, https://mintcdn.com/verifyyou/KqaO94oxL_imvB_J/logo/light.svg?w=560&fit=max&auto=format&n=KqaO94oxL_imvB_J&q=85&s=6c167b05c8155dd4d78bbce187be1896 560w, https://mintcdn.com/verifyyou/KqaO94oxL_imvB_J/logo/light.svg?w=840&fit=max&auto=format&n=KqaO94oxL_imvB_J&q=85&s=d1412be0ee7285ca0992c19602b9854a 840w, https://mintcdn.com/verifyyou/KqaO94oxL_imvB_J/logo/light.svg?w=1100&fit=max&auto=format&n=KqaO94oxL_imvB_J&q=85&s=619cc9cc07c53ffe79922b8796ba2b35 1100w, https://mintcdn.com/verifyyou/KqaO94oxL_imvB_J/logo/light.svg?w=1650&fit=max&auto=format&n=KqaO94oxL_imvB_J&q=85&s=642a6d6fa905ee5dfc192cfe46e0f802 1650w, https://mintcdn.com/verifyyou/KqaO94oxL_imvB_J/logo/light.svg?w=2500&fit=max&auto=format&n=KqaO94oxL_imvB_J&q=85&s=ac2fca97314e055caeaec5c2ef20f41a 2500w" />

      <button className="vy-car-arrow" aria-label="Previous stage" onClick={() => { const s = Array.from(document.querySelectorAll('.vy-car-slide')); for (const el of s) el.setAttribute('data-pos', String((parseInt(el.getAttribute('data-pos'), 10) + 1) % 3)); for (const el of document.querySelectorAll('.vy-st')) el.classList.remove('vy-on'); const f = s.find((el) => el.getAttribute('data-pos') === '0'); document.getElementById('st' + f.id.slice(2)).classList.add('vy-on'); }}>
        <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round">
          <path d="m15 5-7 7 7 7" />
        </svg>
      </button>

      <button className="vy-car-arrow" aria-label="Next stage" onClick={() => { const s = Array.from(document.querySelectorAll('.vy-car-slide')); for (const el of s) el.setAttribute('data-pos', String((parseInt(el.getAttribute('data-pos'), 10) + 2) % 3)); for (const el of document.querySelectorAll('.vy-st')) el.classList.remove('vy-on'); const f = s.find((el) => el.getAttribute('data-pos') === '0'); document.getElementById('st' + f.id.slice(2)).classList.add('vy-on'); }}>
        <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round">
          <path d="m9 5 7 7-7 7" />
        </svg>
      </button>
    </div>
  </div>
</div>

## Why the gate holds

Each password is a claim ticket. We only hand one to a person who just proved, on camera, that they are **live** and **unique**. Your survey platform enforces the ticket with its own built-in gate: Alchemer's <a href="https://help.alchemer.com/help/login-password-action">Login/Password action</a>, or Qualtrics' Authenticator, set to individual one-time passwords that deactivate after use. Your platform's feature, your platform's wording.

So every cheap trick fails: a shared link carries a spent password, a guessed password does not exist, a bot never earns one, and the same face can never get a second one for the same thing, on any device.

One honest limit: the check proves a real, unique human, and says nothing about how carefully they answer. Keep your speeder and attention checks.

## What we never touch

No photo is shared with you or with the platform on the other end, only a yes or no. You receive a verdict and a password, never a face, a name, or personal information.

## What it costs

Pricing depends on your volume and your use case. Tell us what you are running and we will give you a number. Blocked traffic never enters your data.

## Set it up on your platform

Four platforms have a full step-by-step guide. Pick yours and follow it, no code on any of them.

<CardGroup cols={2}>
  <Card title="Qualtrics setup" icon="sliders" href="/docs/guides/qualtrics">
    Five steps, no code.
  </Card>

  <Card title="Alchemer setup" icon="sliders" href="/docs/guides/alchemer">
    Five steps, no code.
  </Card>

  <Card title="Google Forms setup" icon="table" href="/docs/guides/google-forms">
    Five steps, with a script for the response sheet.
  </Card>

  <Card title="Tally setup" icon="clipboard-list" href="/docs/guides/tally">
    Five steps, with a webhook.
  </Card>
</CardGroup>

## Works on more than these four

Nothing about the mechanism is specific to one platform. The check and the single-use credential are always the same; only the platform's own lock changes shape to fit. So the gate works anywhere you can hand each respondent a link or password that works exactly once.

| Platform                  | The credential               | The platform's own lock                                                                                |
| ------------------------- | ---------------------------- | ------------------------------------------------------------------------------------------------------ |
| **Qualtrics**             | A one-time code on the link  | The Authenticator in Survey Flow, where each code authenticates exactly once                           |
| **Alchemer**              | A one-time password          | The Login/Password action, individual one-time passwords that deactivate after use                     |
| **Tally**                 | A one-time token on the link | A hosted gate opens the form only for a valid token, and a webhook removes anything that slips through |
| **Typeform, Jotform**     | A one-time token on the link | The same hosted gate, no guide written yet                                                             |
| **Google Forms**          | A one-time token in a field  | A small script checks each submission and removes the ones without a valid token                       |
| **Your own survey stack** | A one-time token             | Your code asks us whether a token is real and unused before it saves the response                      |

The strength of the lock varies a little by platform. Qualtrics and Alchemer enforce it server-side before a single question shows, which is why those two came first, but the hosted wrapper plus uniqueness protect every platform. We are actively building out more guides.

**Not sure about your platform?** At the top of this page, open the **Copy page** menu and pick **Open in Claude** or **Open in ChatGPT**. It carries this page across, including the table above, so you can ask whether HumanCheck works with your tool and get an answer grounded in how the gate actually works.

Curious what the respondent goes through? See [what your users see](/learn/what-your-users-see).
