How it works
One API client, three galleries
This site keeps no images of its own. They're all in one Pixel Sentinel account (skeeter@pixelsentinel.net), and every page asks the Pixel Sentinel Client API for them while it renders.
The site's server gets a token
It runs on Cloudflare Workers with an API client's ID and secret as secrets. It swaps them for an access token at
POST /oauth/token(OAuth 2.0 client credentials) and reuses the token for an hour. The browser never sees either.It lists the images for the page
Pixel Sentinel has no folders, so the gallery is part of each image's name:
photo--harbor-at-golden-hour.jpg. A gallery page isGET /client/v1/images?q=photo--. Open “API calls” at the foot of any page to see exactly what it asked for.The page carries scrambled images only
Each picture is an
<img>pointing at the scrambled copy, marked withdata-pg. That's all a crawler, an AI scraper or “Save image as…” ever gets.embed.js draws the real picture
Pixel Sentinel's loader script asks for a one-time, freshly shuffled copy of each image and reassembles it on a canvas over the
<img>. Pixel Sentinel only answers when the page's site is on the account's approved list, so the same HTML copied to another site shows scrambled pictures.
What each page calls
| Page | API calls | Scopes |
|---|---|---|
| Home | GET /client/v1/images?q=photo--&limit=6 (and art--, graphics--) | images:read |
| A gallery | GET /client/v1/images?q=art--&limit=24&offset=… | images:read |
| An image | GET /client/v1/images/{id} | images:read |
| Unprotected | GET /client/v1/images?q=open-- (the pictures are plain files on this site) | images:read |
| Compare | GET /client/v1/patrols, then GET /client/v1/patrols/{id} | patrols:read |
| Manage: overview | GET /client/v1/account, PUT /client/v1/domains | account:read, domains:write |
| Manage: images | GET, POST /client/v1/images; DELETE …/{id}; POST …/{id}/download-link | images:read, images:write, links:write |
| Manage: generate with AI | Workers AI (FLUX.1 schnell), then POST /client/v1/images | images:write |
| Manage: traffic | GET /client/v1/traffic?days=…&image=… | traffic:read |
| Manage: patrols | GET, POST /client/v1/patrols; GET …/{id}; GET …/{id}/report.csv | patrols:read, patrols:write |
The images
All of them were made with FLUX.1 schnell on Cloudflare Workers AI from the prompts in scripts/prompts.json, then uploaded with the Python sample's seed.py. The manage area can generate more and uploads them the same way.