Skip to content

Szymdows/szymdows-captcha

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Szymdows CAPTCHA - Frontend Widget

Fast. Private. Human. A behaviour-based CAPTCHA widget with no tracking, no cookies, and no third-party calls. One script tag to install.


What is this?

This is the open-source frontend for Szymdows CAPTCHA - a privacy-friendly alternative to reCAPTCHA and hCaptcha.

Instead of making users squint at blurry traffic lights, Szymdows CAPTCHA asks them to drag a shape into a target zone or tap tiles in a sequence. It watches how they move - the speed, the curve, the hesitation - and uses that to decide if it's a human. No accounts needed. No data sold. No Google.

This repo contains:

  • szymdows-captcha.js - the widget script that goes on websites
  • assets/icon.png - the widget icon

The documentation page:

The scoring backend is proprietary and not in this repo. This is intentional - keeping the detection logic private makes it harder for bots to reverse-engineer and defeat. The frontend you see here is everything a website owner needs.


Quick install

Paste this into the <head> of any HTML page:

<script src="https://cdn.szymdows.com/szymdows-captcha.js"></script>

Then put a <div> where you want the CAPTCHA to appear:

<div id="my-captcha"></div>

Then show it with a couple of lines of JavaScript:

<script>
  SzymdowsCaptcha.render('my-captcha', {
    onSuccess: function(token) {
      // User passed! Enable your submit button, send the token to your server, etc.
      document.getElementById('submit-btn').disabled = false;
    },
  });
</script>

That's it. No npm. No build tools. No configuration.


Full usage

Show on page load (most common)

<div id="my-captcha"></div>
<button id="submit-btn" disabled>Submit</button>

<script>
  SzymdowsCaptcha.render('my-captcha', {
    onSuccess: function(token) {
      // token is a signed string - send it to your server
      document.getElementById('submit-btn').disabled = false;
    },
    onFail: function() {
      // Score too low - widget retries automatically after 2.5s
      document.getElementById('submit-btn').disabled = true;
    },
    onExpire: function() {
      // Auto-resets after 5 minutes so old tokens can't be reused
      document.getElementById('submit-btn').disabled = true;
    },
    theme: 'auto', // 'light' | 'dark' | 'auto' (follows OS setting)
  });
</script>

Show only when the user clicks submit

<div id="my-captcha" style="display:none"></div>
<button id="submit-btn">Submit</button>

<script>
  document.getElementById('submit-btn').addEventListener('click', function() {

    // Already verified? Submit straight away
    if (SzymdowsCaptcha.isVerified('my-captcha')) {
      sendForm(SzymdowsCaptcha.getToken('my-captcha'));
      return;
    }

    // Show and load the CAPTCHA
    document.getElementById('my-captcha').style.display = 'block';
    SzymdowsCaptcha.show('my-captcha', {
      onSuccess: function(token) { sendForm(token); },
    });

  });
</script>

All methods

Method Returns Description
SzymdowsCaptcha.render('id', opts) - Show the CAPTCHA widget inside the element with that id
SzymdowsCaptcha.show('id', opts) - Same as render() - friendlier name for on-demand use
SzymdowsCaptcha.getToken('id') string | null Get the token after the user passes (send this to your server)
SzymdowsCaptcha.isVerified('id') boolean Check if the user has already passed
SzymdowsCaptcha.reset('id') - Clear the result and load a fresh challenge

All options

Option Default Description
onSuccess null Function called when the user passes. Receives the token as its first argument.
onFail null Function called when the score is too low. Widget auto-retries after 2.5s.
onExpire null Function called when the 5-minute auto-reset fires.
autoReset true Auto-reset after 5 minutes so stale tokens can't be reused.
theme 'auto' 'light', 'dark', or 'auto' (follows the user's OS preference).

Verifying the token on your server

When a user submits your form, send the token to your server and check it:

// Node.js / Express example
app.post('/submit', async function(req, res) {

  const response = await fetch('https://captcha.szymdows.com/__szc/verify-token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ token: req.body.captchaToken }),
  });

  const result = await response.json();
  // result = { valid: true, score: 0.87 }
  // or      { valid: false, error: "Token expired" }

  if (!result.valid) {
    return res.status(403).json({ error: 'CAPTCHA check failed' });
  }

  // Safe to process the form
});

Always verify on your server. Never trust a token just because it arrived - always check it server-side before processing a form submission. Tokens are single-use and expire after 60 seconds.


Browser support

Browser Minimum version
Chrome / Edge 80+
Firefox 75+
Safari 13.1+
iOS Safari 13.4+
Samsung Internet 12+

Works on desktop and mobile. Touch, mouse, and keyboard (arrow keys) all supported.


Privacy

  • ✅ No cookies set
  • ✅ No user fingerprinting
  • ✅ No calls to Google, Meta, or any third party
  • ✅ Movement data is processed in real-time and never stored
  • ✅ No accounts or API keys required for website owners

Project structure

szymdows-captcha/
│
├── szymdows-captcha.js   ← The widget (this is what websites load)
└── assets/
    └── icon.png          ← Widget icon shown in the header

The entire widget is a single vanilla JavaScript file with no dependencies. It injects its own styles, loads its own fonts, and works in any environment - plain HTML, React, Vue, WordPress, Webflow, anything.


Contributing

Contributions are very welcome! Here's how to get started - it's simpler than most projects because there's no build step.

What can I contribute?

  • Bug fixes - if something doesn't work, open an issue or a PR
  • Browser compatibility fixes - found a browser where it breaks? Please report it
  • Accessibility improvements - making the widget work better for keyboard/screen reader users
  • New challenge types - ideas for new human-verification interactions (open an issue to discuss first)
  • Documentation improvements - clearer wording, more examples, better explanations
  • Translations - the widget text is currently English only

Getting started

  1. Fork this repo - click the Fork button at the top right of this page

  2. Clone your fork to your computer:

    git clone https://github.com/Szymdows/szymdows-captcha.git
    cd szymdows-captcha
  3. Open https://szymdows.com/captcha in your browser - this is the documentation page and a good place to see the widget in action

  4. Make your changes to szymdows-captcha.js

  5. Test by opening a simple HTML file - no build step needed, just open it in a browser:

    <!DOCTYPE html>
    <html>
    <head>
      <script src="./szymdows-captcha.js"></script>
    </head>
    <body>
      <div id="test-captcha"></div>
      <script>
        SzymdowsCaptcha.render('test-captcha', {
          onSuccess: function(token) { console.log('Token:', token); }
        });
      </script>
    </body>
    </html>
  6. Open a Pull Request - describe what you changed and why

Guidelines

  • Keep it vanilla - no frameworks, no npm packages, no build tools. The whole point is that this loads with a single script tag.
  • Keep it small - every byte added to the script is a byte every website using this has to download.
  • Test on mobile too - open your test file on your phone or use browser DevTools to simulate touch.
  • One thing per PR - smaller, focused pull requests are much easier to review than large ones.
  • Open an issue first for big changes - if you want to add a new challenge type or change something fundamental, open an issue to discuss it before writing code. Saves everyone time.

Reporting bugs

Open an issue and include:

  • What browser and version you're using
  • What you expected to happen
  • What actually happened
  • Any error messages from the browser console (press F12 to open it)

Why is the backend closed source?

The verification logic - how movement paths are scored, what counts as "bot-like" behaviour - is kept private on purpose. If it were open source, bot authors could read it, understand exactly what patterns get flagged, and write bots that pass every time.

The frontend (this repo) is fully open so you can see exactly what data is collected and sent, verify there's no tracking, and audit the code you're loading onto your website. That's the part that matters for trust.


Licence

MIT - free to use, modify, and distribute. See LICENSE for the full text.

The backend service at captcha.szymdows.com is proprietary.


Made by Szymdows Visit my portfolio: https://szymdows.com

About

Fast, private, behaviour-based CAPTCHA widget. No tracking, no cookies, no third-party calls. One script tag to install.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors