openpuzzle-captcha/README.md
2025-12-28 16:26:08 +03:00

4.3 KiB

Open Puzzle Captcha

Open Puzzle Captcha is a open-source interactive captcha which use puzzle solve for bot filtration
Open Puzzle Captcha DEMO

How use NPM module

You can use NPM module for generate tasks. Install the module:

npm i openpuzzle-captcha

It's required: install Graphics Magick

And include it in the project:

const opc = require("openpuzzle-captcha");
opc.generateTask("/path/to/images/folder").then(console.log);

How add the widget

Clone the repository:

git clone https://git.fullgream.tech/fullgream/openpuzzle-captcha.git

You can include this widget in your HTML (take code from widget/opc-widget.html):

    <div value="" success="false" class="opc-widget" captcha-url='http://example.org/<captcha_id>' style='border: 1px solid; border-color: #AFAFAF; border-radius: 15px; width: 365px; padding-top: 10px; padding-left: 10px; font: 12px system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif'>
        <canvas width="350" height="350">Your browser don't support Canvas</canvas>
        <!-- Required by license -->
        <a href="https://git.fullgream.tech/fullgream/openpuzzle-captcha">OpenPuzzle Captcha</a>
    </div>

And in your Java Script:

// Take opc-widget.js from widget/opc-widget.js
import { initOPCWidgets } from "/path/to/opc-widget.js";
initOPCWidgets();

In HTML attribute "captcha-url", fill the address of API.

How it works

Open Puzzle Captcha separated by two parts - client widget (for next: widget) and open puzzle captcha API (for next: API). For first, the widget sends request to the API, the API takes random picture (150x150px), splits the picture by 9 fragments (in future version, I can add 4 parts mode), adds changes for this fragments (It's important. After it, fragments change their hash-sum). the API generates unique key for every fragment and summorize it by solve key. After it, the API shuffle the parts of picture and send them as response to the widget. The widget don't know which combination is correct (It dictated by abuse safety), the widget spawns the parts of picture in field (for next: shards) and waits before user not solve the puzzle. Every cell of the field has number 1..9:

1 2 3
4 5 6
7 8 9

When user grabbing the shard to the cell, the widget remembers number of this cell and writes key of the cell to the chain of responses. It forms answer of the Captcha. For Example:

1d23af 2fde09 e389a1
4f441d 5cd456 6ff1ce
7a1def 8df780 9a1d8f

Captcha answer: 1d23af2fde09e389a14f441d5cd4566ff1ce7a1def8df7809a1d8f
This answer will sent to the API and after it, the API compare the answer with the correct solve and return result to widget. If captcha answer is wrong, the API generates new captcha's task and deletes old. Else - the API leave the Success Code which may use for forms in the website. More details: [In develop]

API

The widget sends GET-request to website which includes in attribute "captcha-url". The widget awaits next JSON response:

{
    "isError": false,
    "mode": "3x3",  // <-- for now, supports only 3x3 mode
    "fragments": {
        "<fragment-id-1>": "http://url.of/image's/fragment/1",
        "<fragment-id-2>": "http://url.of/image's/fragment/2",
        ...
        "<fragment-id-9>": "http://url.of/image's/fragment/9"
    }
}

After user solve the captcha and press button "Send Result", the widget send POST-request to the same address which contains next JSON body:

{
    "answer": "<captcha-answer>",
}

And we have 2 awaited ways:
First: Correct answer, server send:

{
    "isError": false,
    "isSuccess": true,
    "successCode": "<secret-success-code>"
}

The Widget get successCode and change attribute "value" inside itself to successCode's value.
Second: Wrong answer, server send:

{
    "isError": false,
    "isSuccess": false,
    "tryAgain": "/path/to/new/captcha"
}

API errors

If in the runtime in the API occured errors, the widget get errors from the API:

{
    "isError": true,
    "message": "Error message"
}