Aperi'Solve puts sixteen steganography analyzers behind one upload form
Steganalysis web platform
At a glance
- What is it?
- Aperi'Solve is a self hosted web platform that runs sixteen steganography tools in parallel over an uploaded image and shows the results side by side, with bit plane visualisation and an in-app handbook. It suits CTF players and image forensics teams who want one repeatable workflow instead of a folder of command lines.
- Who is it for?
- Adopt Aperi'Solve when you need repeatable image steganalysis over many submissions, since the parallel worker, the password aware extractors and the cached derived images remove most of the repetitive work, and it can be self hosted with Docker Compose. Do not adopt it for audio, text or file carriers, because the documented analysis surface is images.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 25, 2026, and from our analysis. They are not legal advice.
Editorial analysis
One upload, sixteen analyzers, one screen
The problem Aperi'Solve addresses is mundane and real. Finding hidden data in an image normally means knowing which tools exist and remembering their flags, and the classic workflow is a terminal where you try binwalk, then foremost, then zsteg, then a password protected extractor you can only guess at if you remember the tool supports one. Aperi'Solve turns that into a web form. The README describes it as an open-source steganalysis web platform that performs automated analysis on images to detect and extract hidden data using common steganography tools and techniques, and the analyzers run in parallel with per-tool success and no-result badges, plus one-click download of whatever was extracted.
The sixteen tools and what each one is good for
The tool list is the substance of the project, and each entry is paired with a job description in the README. binwalk covers embedded archives, exiftool covers metadata and geolocation, file detects MIME type and format, GraphicsMagick identify reports image info and properties, and foremost carves files. Then come the format specific extractors: jsteg for JPEG LSB, jpseek and jphide for JPEG steganography with a password, openstego and steghide for password based extraction, outguess for extraction with a password plus deep analysis, pcrt for PNG check and repair, pngcheck for PNG validation, strings for embedded text, and zsteg for LSB text and data extraction. Two of these, jpseek and jphide, are the same upstream tool, which is why the README groups them on one line.
Bit planes and the IHDR recovery database
Beyond running the tools, the platform gives you a way to look at the image itself. Each bit layer, LSB and the others, can be visualised per image channel across R, G, B and Alpha. There is also a color remapping feature that generates eight random palette remap variants, which is a way to make faint LSB structure visible to the eye. One component is less common: the `initdb` service is a one-shot container that creates the tables and pre-fills an IHDR CRC recovery database. That database exists because PNG chunks carry a CRC, so a modified chunk can sometimes be repaired or reconstructed, and the recovered data is indexed there. It is the piece of the system with no obvious equivalent in a hand-run tool chain.
A worker queue, a cleanup cron and explicit ceilings
The architecture is described as Docker Compose services, and the separation is the point. The `web` service is a Flask app served by gunicorn with Jinja templates and a vanilla JavaScript frontend. The `worker` service is an RQ worker that runs the analyzers for each submission, fanning out to one thread per tool. The `cron` service is an RQ cron scheduler that runs the retention cleanup away from the request path. Redis serves as the RQ broker on DB 0 and as rate limiter storage on DB 1, Postgres stores image metadata and submission status, and `rqdashboard` gives queue monitoring bound to localhost:9181. Identical submissions are deduplicated by a content hash, and derived images are cached with long-lived immutable HTTP headers, so repeat traffic is cheap. Results are not kept forever: `MAX_STORE_TIME=259200` seconds is the retention window, `CLEANUP_INTERVAL_SECONDS=900` is how often the cron runs, `REMOVAL_MIN_AGE_SECONDS=300` sets a floor on how recently an item must have been submitted before it can be removed, and `MAX_PENDING_TIME=600` bounds queued work.
Self hosting with the four command quick start
Running your own instance requires Docker and Docker Compose, and the start is deliberately short:
git clone https://github.com/Zeecka/AperiSolve.git
cd AperiSolve
cp .env.example .env
docker compose up -dAfter that, the README says to browse to http://localhost:5000/. Copying the example environment file matters, because the stack reads its settings from `.env` and the compose file defines a `WEB_APP_PORT` that defaults to 5000. Two of those settings carry warnings in the file itself. `CLEAR_AT_RESTART=0` must stay at 0 unless you want a throwaway instance, because a value of 1 drops the whole database and every stored result each time the stack starts, and `MAX_CONTENT_LENGTH=3145728` caps the upload size at 3 MiB. Ads and analytics are off by default; `GOOGLE_ADS_TXT`, `CUSTOM_EXTERNAL_SCRIPT`, `SITE_BASE_URL` and Sentry are all opt-in. The compose file also puts explicit ceilings on the services, with the web service limited to 2g of memory and 1.5 CPUs, because analyzers are CPU-bound and would otherwise starve whatever else shares the host. Rate limiting is applied per endpoint and backed by Redis.
Adding an analyzer means writing one subclass
The extension story is unusually clean, and it is the reason to run your own instance rather than relying on the hosted one. Adding an analyzer is a single file: you subclass `SubprocessAnalyzer`, set a few class attributes among them `name`, `has_archive`, `needs_password`, `deep_only` and `display_order`, and install the tool in the Dockerfile. The worker run list, the download allow-list and the frontend ordering are then derived automatically, so there is no central registry to edit by hand. The `deep_only` and `needs_password` attributes are the interesting ones, because they let the platform hold back slow analyzers until requested and flag the ones that need a password from you. The mechanics are written up in `docs/adding-analyzer.md`.
The in-app wiki and seven interface languages
The platform carries its own handbook at `/wiki`, described as a HackTricks-style steganography handbook written as Markdown. It includes a triage methodology, a decision tree cheatsheet, technique pages per medium, and a guide per analyzer. The medium coverage is broader than the tool coverage, which is interesting: the wiki spans image, audio, text and files, while the analyzers themselves are image oriented. The interface is available in English, French, Spanish, German, Russian, Chinese and Portuguese under language-prefixed URLs such as `/fr/` and `/es/`, with translation files published through `flask-babel`. Taken together, the wiki and the parallel analyzers are the two halves of the product: one explains how to think about a carrier, the other does the work.
MIT licensed, Python 3.12 floor, and tools compiled into the image
The licence is MIT, so modification and redistribution are straightforward provided the notice travels with the code. The Python floor is 3.12, and the runtime dependencies are a conventional Flask stack with `Flask-SQLAlchemy`, `numpy`, `Pillow`, `redis`, `rq`, `psycopg2-binary` and `gunicorn`. The part worth reading twice is the Dockerfile. The image is built from `python:3.14-slim`, and the analyzers are compiled into it rather than installed at runtime: OpenStego is fetched as a versioned Debian package, jsteg is cloned and built from Go source at a pinned commit, and the jpseek and jphide C sources are patched and compiled during the build, with vendored autotools helper scripts copied in so the configure step works on aarch64 without a build time download. The releases move steadily, with 3.7.12 published on 2026-10-14 after 3.7.11 and 3.7.10, and the last push was on 2026-10-14.
Editorial conclusion
Adopt Aperi'Solve when you need repeatable image steganalysis over many submissions, since the parallel worker, the password aware extractors and the cached derived images remove most of the repetitive work, and it can be self hosted with Docker Compose. Do not adopt it for audio, text or file carriers, because the documented analysis surface is images. Verify first that the analyzers you depend on are present in your build, since the tool binaries are compiled into the image rather than installed at runtime, and check the `CLEAR_AT_RESTART` setting in `.env` before your first `docker compose up`.
Frequently asked questions
How do I self host Aperi'Solve?
Clone the repository, copy `.env.example` to `.env` and start the stack with `docker compose up -d`, then browse to http://localhost:5000/. Docker and Docker Compose are required.
Which steganography tools does Aperi'Solve run?
The README lists sixteen analyzers including binwalk, exiftool, file, foremost, jsteg, jpseek and jphide, openstego, outguess, steghide, zsteg, strings, pcrt and pngcheck, each running in parallel on the submitted image.
How do I add my own analyzer to Aperi'Solve?
Subclass `SubprocessAnalyzer` in a single file, set class attributes such as `name`, `has_archive`, `needs_password`, `deep_only` and `display_order`, and install the tool in the Dockerfile. The run list, download allow-list and frontend order are derived automatically.
Will restarting the Aperi'Solve stack delete my results?
Only if you set `CLEAR_AT_RESTART=1` in `.env`. The example file warns that 1 drops the whole database and stored results every time the stack starts, so the default of 0 is meant to stay as it is.
Does Aperi'Solve show ads or send analytics by default?
No. Ads and analytics are disabled by default, and each integration, including `CUSTOM_EXTERNAL_SCRIPT`, `GOOGLE_ADS_TXT`, `SITE_BASE_URL` and Sentry, is opt-in through environment variables in `.env.example`.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/zeecka-aperisolve)Was this useful?