It noses out the screenshot you forgot.
100 screenshots in, 1 file out. 100 of 100 hidden codes found in Chromium, 99 in Firefox.
Method: 100 made-up phone screenshots drawn by src/core/sample.js (8 kinds, 31 in dark mode, 20 in small type), one made-up code in each. Read in the page, then I searched for each code and checked that the lit words sit on it. Then I exported, reopened with the network off, and repeated 20 of the searches: 20 of 20 in both. Ryzen 5 7500F, Chromium 153, Firefox 155. Raw numbers in bench/results.json. Synthetic screenshots are clean. Yours will be harder.
I save screenshots so I'll remember things. Then I can't find them. Snootling reads the words in them inside a browser tab, lets you search, and saves the pile as one HTML file you keep. Nothing is uploaded and nothing needs an account.
| The usual | With Snootling |
|---|---|
| 100 thumbnails. One is a boarding pass. You scroll and squint. | Type gate e29. One picture is left and the words are lit. |
| The search lives in one app on one phone. | One .html file. Any browser opens it, offline. |
| Your pictures sit in someone's cloud index. | A page whose policy blocks its own network requests. The tests record every request. |
Your screenshots are a file you own.
One command, no build step. The page is a single file.
curl -LO https://raw.githubusercontent.com/Arthur031221/Snootling/main/dist/snootling.html && open snootling.html
Linux
curl -LO https://raw.githubusercontent.com/Arthur031221/Snootling/main/dist/snootling.html && xdg-open snootling.html
Windows (PowerShell)
iwr https://raw.githubusercontent.com/Arthur031221/Snootling/main/dist/snootling.html -OutFile snootling.html
ii snootling.html
Host it yourself
Copy dist/snootling.html to any static host. It needs no server code. .github/workflows/pages.yml publishes it to GitHub Pages when you run it by hand.
1. Open snootling.html and drop your screenshots on it (PNG, JPEG or WebP).
2. Type words you remember, like: gate e29
3. Click a result. The matched words light up in the full picture.
4. Export searchable file. You get snootling-YYYYMMDDHHMM.html.
5. Open that file in any browser. Same search, no app, no network.
Not sure yet? "Try the sample screenshots" draws 24 fake ones and reads them right there.
| Chromium 153 | Firefox 155 | |
|---|---|---|
| Screenshots read | 100 of 100 in 9.8 s | 100 of 100 in 10.9 s |
| Code found in the results | 100 | 99 |
| Right picture is the first result | 99 | 98 |
| Lit words sit on the code | 100 | 99 |
| Exported file | 18.2 MB | 14.5 MB |
| Reopened offline, 20 searches | 20 of 20 | 20 of 20 |
| Requests to anything not local | 0 | 0 |
Found means the picture is in the results. In each browser one search needed the closest match fallback, described below. Reading uses 4 workers on this 12 thread machine. The time moved between 10 and 20 s from run to run, so a phone or a laptop on battery will be slower. The builder itself is 7.9 MB because the OCR engine and its English model live inside it.
- The page carries tesseract.js 7, its WebAssembly core and the English model, so nothing is downloaded. Its policy sets
default-src 'none'and allowsconnect-srcforblob:anddata:only, so its own code can't fetch or post anything. A policy doesn't cover page navigation, so it guards but doesn't prove. The tests record every request the page makes and require all of them to be local. - Each picture is read once at up to 1280 px wide. The word boxes are scaled back to the original size, so the glow lands on the right pixels at any zoom.
- Search matches words as you type.
wififindsWi-Fi. One misread character is forgiven for longer words, and look-alikes (0andO,1andl) are forgiven for codes. If no picture has every word, you get the closest ones, with rare words counting more. In my runs the failure was usually one unreadable word, so I'd rather show near misses than an empty page. - Your library stays in this browser's IndexedDB until you clear it. The saved file holds the viewer, the text, the word boxes and the original pictures. File names and recognized text go in as escaped data, not markup.
- Opening a saved file inside the builder reads its data and runs nothing from it.
- English only. Handwriting, tiny grey text and non-Latin scripts aren't good.
- The 100 screenshot test is synthetic and clean. I haven't measured real phone screenshots, so treat 99 of 100 as a ceiling.
- Big display text next to a small label can lose the label. That's why the closest match fallback exists.
- The saved file holds your full screenshots. Anyone with the file can read what's in them, passwords included. The export dialog says so before it saves.
- A library is capped at 100 pictures and 50 MiB, with a smaller JPEG option on export.
- Chromium and Firefox are tested. Safari isn't. Playwright WebKit doesn't start on my machine.
PixelFind is a browser app with local OCR, and its folder picker needs Chrome or Edge. Gyotaku is a desktop app for searching screenshots, and a good one. Windows Photos and Pixel Screenshots read text on devices that support them. Snootling is the narrow case in between: a pile of files, any browser, and a result file you can hand to someone or park on a drive.
See CONTRIBUTING.md. Run npm ci, npm test and npm run test:e2e. Third party files are listed in THIRD_PARTY.md. MIT licensed.
