Block re-uploads of removed images with hash lists
Hash lists compare every image upload with fingerprints of images your project has removed, so a resized or recompressed copy is flagged or blocked.
·4 min read
Hash lists
Moderation
Images
Removing an image rarely ends the matter. The same picture comes back as a screenshot, a cropped repost or a recompressed copy from another site, and each copy has different bytes. Comparing file checksums misses all of them. Release 2026.5 adds hash lists: fingerprints of images your project never wants again, compared with every image upload.
Fingerprints that survive re-saving
CalmLens fingerprints each image upload with a PDQ perceptual hash, a 256-bit hash of what the picture looks like rather than how the file is encoded. Resizing, recompressing, brightening or saving in another format changes the file but barely changes the hash, so copies of one image usually sit within a few bits of each other. Unrelated images are around 128 bits apart.
PDQ is also the format shared lists of known images use, so a hash computed by another system can go straight into a list. Every image asset reports its own hash as content.image.perceptualHash (64 hexadecimal characters), with content.image.perceptualHashQuality describing how much detail it captured.
Flag lists and block lists
Each list has one of two actions:
Flag records the match on the asset and in an asset.hash-matched event, without changing the moderation decision.
Block blocks close matches, 16 bits apart or fewer, and flags looser ones up to 31 bits apart.
The two thresholds keep the automatic block for near-identical copies, while looser matches are only recorded for someone to check.
A block raises the decision to at least blocked. The upload is still moderated as usual, so a stricter policy decision, such as purged, still applies.
What a match looks like
Matches 31 bits apart or fewer are recorded on the asset as classification.moderation.raw.hashMatches, up to 10 per asset: block-list matches first, then the closest within each action. Each one names its list and entry, the distance in bits and the action it took (flag or block). When a block list decides the asset, classification.moderation.source is hash-list, so you can tell a hash block from a policy block.
The asset.hash-matched event names the list of the first recorded match: a block list when one matched, otherwise the closest list. Subscribe a connector to it to alert your moderators when a listed image comes back, whether the list flags or blocks.
A hash with a quality below 50 comes from a flat or featureless image and is never matched, whether it belongs to an upload or a list entry.
Visually similar images can match even when they aren't copies: two posts built on the same meme template, or screenshots of the same app screen. Start with flag lists while you learn what your entries catch, and switch a list to block once its matches look right. Changing a list's action applies to later uploads.
Adding images
The quickest way to list an image is from its asset page in the portal: add the asset to a list, and future uploads of that image match it. Only images that finished processing have a hash to add. You can also paste a PDQ hash computed elsewhere, one entry at a time.
Through the API, create a list:
{ "name": "Removed images", "action": "block" }
Then add an image asset to it, with an optional label for your own reference:
To add a hash from another system, send hash and, when you know it, quality instead of assetId. Adding a hash the list already holds returns the existing entry, so a script that imports hashes can run again safely.
Removing an entry stops later uploads matching it. Assets already decided keep their decision.
Limits
A project can hold 50 lists and 10,000 entries across them. Managing lists needs the hash-lists:write permission.
We use essential cookies for sign-in and security. With your permission, functional cookies remember your preferences and Google Analytics measures website use and signups. Optional ad measurement cookies link Google ad clicks to signups. Personalised advertising stays off. Manage cookies