A simple and minimal microservice for generating and validating CAPTCHA.
miniCAP is a simple microservice, written in Python, with only two REST endpoints:
one for creating CAPTCHAs (/api/captcha/generate/
) and one for verifying them
(/api/captcha/validate/
).
Some random samples of CAPTCHAs generated with miniCAP:
Light theme | Dark theme | |
---|---|---|
Only text | ![]() wFKdfr |
![]() N9sx2G |
Text + background noise |
![]() A4G9bu |
![]() D46JLk |
Text + foreground noise |
![]() Sx6pU7 |
![]() 3mtNKE |
Text + background noise + foreground noise |
![]() MdEMFd |
![]() 95ScZ5 |
There are two ways of getting a working copy of miniCAP on your own computer: either
by using Docker or by using directly the source code
in a Python 3
(at least 3.10
) environment. In both cases, the first thing to do is
to get a local copy of this repository, so open up a terminal in the directory where you
want to save the project and clone the repository:
$ git clone https://github.com/ClaudiuGeorgiu/miniCAP.git
This is the suggested way of installing miniCAP, since the only requirement is to have a recent version of Docker installed:
$ docker --version
Docker version 28.0.1, build 068a01e
The official miniCAP Docker image is available on Docker Hub (automatically built from this repository):
$ # Download the Docker image.
$ docker pull claudiugeorgiu/minicap
$ # Give it a shorter name.
$ docker tag claudiugeorgiu/minicap minicap
If you downloaded the official image from Docker Hub, you are ready to use the service,
otherwise execute the following command in the previously created miniCAP/
directory
(the folder containing the Dockerfile
) to build the Docker image:
$ # Make sure to run the command in miniCAP/ directory.
$ # It will download and install all the project's dependencies.
$ docker build -t minicap .
miniCAP is now ready to be used, run the following command to start the service on port
8000
:
$ docker run --rm -p 8000:8000 minicap
miniCAP microservice is now running, see the usage instructions for more information.
The only requirement of this project is uv.
Run the following commands in the main directory of the project (miniCAP/
) to
install the needed dependencies:
$ # Make sure to run the command in miniCAP/ directory.
$ uv sync --frozen --no-dev
miniCAP is now ready to be used, run the following command to start the service on port
8000
:
$ # Make sure to run the command in miniCAP/ directory.
$ uv run -m minicap.main
miniCAP microservice is now running, see the usage instructions for more information.
When miniCAP microservice is running, it exposes only two REST endpoints for interacting with CAPTCHAs:
-
POST
/api/captcha/generate/
- returns a new CAPTCHA image in the response body (of typeimage/png
) and aCaptcha-Id
header needed to validate the CAPTCHA. This endpoint needsPOST
instead ofGET
requests because every request generates a newCaptcha-Id
that is saved into the database (GET
requests should be idempotent). -
POST
/api/captcha/validate/
- validates a CAPTCHA by accepting a request containing a previously generatedCaptcha-Id
and the text displayed in the CAPTCHA. The request must be a JSON containing a text fieldid
with the value ofCaptcha-Id
header and a text fieldtext
with the solution of the CAPTCHA.
Tip
While the microservice is running, the complete REST OpenAPI documentation is available at http://localhost:8000/docs.
Note
Each CAPTCHA is deleted from the database after:
- 10 minutes since its creation
- a successful validation
- 3 unsuccessful validation requests
-
Request the generation of a new CAPTCHA image and save the result into a file (e.g.,
CAPTCHA.png
). Take note of the value ofCaptcha-Id
response header, as it will be needed later for the validation request:$ curl -v -s -X POST "http://localhost:8000/api/captcha/generate/" --output CAPTCHA.png * ... < HTTP/1.1 200 OK < captcha-id: 1cc70567-8124-40f8-ba74-062c896f1535 < ...
-
Open the file with the CAPTCHA and solve it (e.g., the image displays the string
X575u6
). -
Send the CAPTCHA solution and the value of
Captcha-Id
header back to the server for validation:$ curl -X POST "http://localhost:8000/api/captcha/validate/" \ -H "Content-Type: application/json" \ -d '{ "id": "1cc70567-8124-40f8-ba74-062c896f1535", "text": "X575u6" }' {"status":200,"message":"CAPTCHA validated successfully"}%
import requests
# 1. Generate CAPTCHA and retrieve its id from Captcha-Id header.
res = requests.post("http://localhost:8000/api/captcha/generate/")
res.raise_for_status()
captcha_id = res.headers.get("Captcha-Id")
with open("CAPTCHA.png", "wb") as img:
img.write(res.content)
# 2. Open CAPTCHA image and solve it.
solution = "captcha solution here"
# 3. Validate CAPTCHA.
res = requests.post(
"http://localhost:8000/api/captcha/validate/",
json={"id": captcha_id, "text": solution},
)
res.raise_for_status()
Run the following command in the main directory of the project (miniCAP/
) to also
install test dependencies (needed only the first time):
$ uv sync --frozen
Then run the following command to execute the automatic test suite:
$ uv run pytest --verbose
Questions, bug reports and pull requests are welcome on GitHub at https://github.com/ClaudiuGeorgiu/miniCAP.
You are free to use this code under the MIT License.