Find Duplicate Images & Videos

Select a folder to scan. Supports images (JPG, PNG, GIF, WebP) and videos (MP4, WebM, MOV).

Ready
0 items

🔬 How pHash Duplicate Detection Works — Complete Guide

Everything you need to know about finding and cleaning up duplicate files with the pHash (Perceptual Hash) algorithm. Scroll down for step‑by‑step instructions, tips, and answers to common questions.

100% Private — Your Files Never Leave Your Computer Everything runs inside your browser. No uploads, no accounts, no tracking. Close the tab and all data is gone.

🔍 What This Tool Does

Sakarto looks inside your images and videos to detect duplicates — not just files with the same name. pHash analyses the frequency content of each image using a Discrete Cosine Transform (DCT). Rather than comparing pixel values or regional averages directly, pHash converts the image into a representation of how much energy lives at different spatial frequencies — similar to how MP3 audio compression works, but for images. Two images with the same or similar frequency fingerprint are grouped as duplicates.

Frequency‑Domain Fingerprinting

Uses a Discrete Cosine Transform instead of pixel comparisons. The result is a hash that is robust to a wide range of image transformations including mild colour edits and re‑compression.

Fewer False Positives

Encodes perceptual structure rather than raw brightness patterns, making it less likely to match unrelated images that happen to share similar overall brightness distributions.

Web Worker Processing

All DCT computation runs in a background Web Worker via OffscreenCanvas, keeping the browser tab fully responsive during scanning.

Fast Mode for JPEG

Reads embedded EXIF thumbnails instead of full images — 5–10× faster with near‑identical accuracy for most photos.

🧠 How the pHash Algorithm Works

Perceptual Hash uses the Discrete Cosine Transform to identify the dominant structural frequencies in an image and encode them as a compact binary fingerprint. Here is the full step‑by‑step process:

  1. Resize to 32×32 Pixels

    Each image is drawn onto a 32×32 canvas. This normalises all images to the same size and gives the DCT a square input of manageable dimensions. In Fast Mode, JPEG files use their embedded EXIF thumbnail at this step — the difference in thumbnail quality has almost no effect on the final hash since DCT encoding is inherently robust to minor quality variations.

  2. Convert to Grayscale

    Each of the 32×32 = 1024 pixels is converted to a grayscale value using the luminance formula 0.299×R + 0.587×G + 0.114×B. The DCT operates on intensity, not colour. Colour information is discarded at this stage — pHash, like all other hash algorithms in Sakarto, is colour‑blind.

  3. Apply a 2D Discrete Cosine Transform

    A separable 2D DCT is applied to the 32×32 grayscale matrix: first row‑wise, then column‑wise. This transforms the image from the spatial domain (pixel positions) into the frequency domain. The result is a 32×32 matrix of DCT coefficients where the top‑left region encodes low‑frequency (coarse structure) information and the bottom‑right encodes high‑frequency (fine detail) information.

  4. Extract the Top‑Left 8×8 Low‑Frequency Coefficients

    Only the top‑left 8×8 = 64 DCT coefficients are kept. These represent the lowest spatial frequencies in the image — the broad shapes, major contrasts, and dominant structural content. High‑frequency detail (fine textures, sharp edges, noise) is discarded. This is what makes pHash robust to re‑compression, mild sharpening, and small scale changes: all of those affect high frequencies far more than low ones.

  5. Compute the Mean of the 64 Coefficients

    The mean (average) of the 64 low‑frequency DCT coefficients is calculated. The DC component at position (0,0) — which represents the overall average brightness — is excluded from this calculation to make the hash invariant to global brightness differences.

  6. Produce the 64‑Bit Hash

    Each of the 64 DCT coefficients is compared to the mean. If a coefficient is above the mean, its bit is 1; if at or below, its bit is 0. The resulting 64‑bit binary string is the pHash fingerprint for this image — a compact encoding of its dominant perceptual structure.

  7. Compare Using Hamming Distance

    To compare two files, their 64‑bit hashes are XOR’d bit by bit. The number of positions where the bits differ is the Hamming distance. A distance of 0 means identical perceptual structure. The similarity threshold slider controls the maximum Hamming distance allowed for two files to be grouped as duplicates. Lower = stricter.

  8. Aspect Ratio Pre‑Check & Video Multi‑Frame Averaging

    Before any hash comparison, pairs where aspect ratios differ by more than 10% are skipped. For video files, 3 frames are extracted at 1.5‑second intervals, each hashed separately, and the 3 hashes are combined by majority vote to produce a single representative hash for the file.

Why is pHash more robust than aHash or dHash? aHash and dHash operate in the spatial domain — they compare pixel values directly. Small changes (re‑compression, sharpening, mild resizing) can flip spatial pixel comparisons. pHash operates in the frequency domain: low‑frequency DCT coefficients encode the “shape” of the image's major structures and are very stable across exactly the kinds of edits that trip up spatial hash methods.

🎚️ Understanding the Hamming Threshold Slider

The Similarity Threshold slider (0–50) controls how many of the 64 hash bits two images can differ on and still be grouped as duplicates. It is the most important control on this page.

Low values (0–5) — Very strict

Only near‑identical images match. Finds exact copies, direct re‑exports, and lossless format conversions. Very few false positives. May miss images with significant edits applied.

Medium values (6–20) — Balanced (default: 10)

Catches resized copies, re‑compressed files, mild colour corrections, and similar edits. The default of 10 is a good starting point. pHash is well‑calibrated at this range: it picks up subtle edits that aHash misses while producing fewer false positives than BlockHash at the same value.

High values (21–50) — Loose

Groups images with broadly similar perceptual structure. Two different photos shot in similar settings may match. Always review groups before acting at these values.

Re‑clustering is instant. When you release the slider, all already‑scanned hashes are re‑grouped in a background Web Worker — no re‑scanning needed. The scan only runs once per folder.
Lower = stricter. The slider measures the maximum number of differing hash bits allowed. A value of 0 means “accept only identical frequency patterns.” A value of 10 means “accept up to 10 bit differences out of 64.”

✅ What It Finds — and What It Might Miss

✅ Finds Well
  • Exact byte‑for‑byte copies
  • The same photo at different resolutions
  • Re‑saved copies in different formats (JPEG → PNG → WebP)
  • Re‑compressed JPEG versions (even at significantly lower quality)
  • Copies with mild colour grading or colour profile changes
  • Images with slight sharpening or noise reduction applied
  • Lightly cropped versions where major structural content remains
  • Videos with similar key‑frame frequency content
⚠️ May Struggle With
  • Rotated or mirrored copies (DCT is not rotation‑invariant)
  • Heavily cropped versions where major structures are removed
  • Dramatic colour or exposure transformations that remap overall structure
  • Stylised versions (e.g. watercolour, posterise, extreme filter effects)
  • Black‑and‑white vs. colour version if luminance structure differs significantly
pHash is a strong all‑purpose algorithm for photo deduplication. For rotated or perspective‑warped copies use ORB Feature Matching. For very noise‑heavy collections, BlockHash may tolerate artifacts better. For copies that differ only in brightness or exposure, dHash is more sensitive.

📋 Step‑by‑Step: How to Use Sakarto pHash

Step 1

Select a Folder to Scan

Click 📁 Select Folder to Scan to open a native folder picker (Chrome / Edge). Or drag and drop a folder onto the page. In Firefox or Safari, use the file input fallback.

Enable Fast Mode for JPEG‑heavy libraries. It reads the embedded EXIF thumbnail instead of the full image — 5–10× faster, with essentially identical hash results because the DCT operates on low‑frequency content that survives thumbnail compression intact.
Step 2

Wait for the Scan

A progress bar shows how many files have been processed. pHash involves a DCT computation per image, which is a little slower than simple pixel hashing, but remains fast enough for most collections. Duplicate groups appear live as they are found. You can start reviewing before the scan finishes.

Step 3

Adjust the Similarity Threshold

After the scan, use the Similarity Threshold slider to tune matching sensitivity. Releasing the slider re‑clusters all results instantly in a background Worker — no re‑scan needed. The default of 10 is well‑calibrated for pHash. Because pHash operates in the frequency domain, it is generally more discriminating than BlockHash at the same threshold value, so you may find the default already works well for your collection.

Step 4

Review the Duplicate Groups

Results are shown in numbered groups. Each group contains files that look similar to each other.

  • Click a card to select it (blue border)
  • Ctrl+Click (or Cmd+Click on Mac) to add to the compare list (purple border)
  • Click the 🔍 icon on hover to preview full size
  • Right‑click any card for the context menu
  • Click & drag on empty space to box‑select multiple cards
Step 5

Compare Side‑by‑Side

Ctrl+Click two or more cards, then click ⚖️ Compare in the toolbar. A modal opens with full metadata (dimensions, size, type, path) and a similarity percentage. For 3+ files, a pairwise similarity matrix is shown. pHash's frequency‑domain encoding means the similarity percentage in the Compare modal is a meaningful indicator of how perceptually close two images are.

Step 6

Take Action — Move, Delete, or Copy

Select files and use the toolbar buttons. With Queue Mode on (recommended), files are staged for review first:

📋 CopyCopy filename(s) to clipboard
📂 MoveStage for move to a named folder
🗑️ DeleteStage for permanent deletion
⚖️ CompareView selected files side‑by‑side
Step 7

Queue Mode — Review Before You Commit

When Queue Mode is enabled (the default), clicking Move or Delete stages files in a queue instead of acting immediately. Switch to the Move Queue or Delete Queue tab in the sidebar to review what's staged, remove individual files, then execute when ready.

With Queue Mode disabled, a confirmation dialog appears and the operation runs immediately after you confirm.

🏛️ Quick Reference — Buttons & Controls

All toolbar buttons, checkboxes, and keyboard shortcuts for Sakarto pHash duplicate finder
Button / ActionWhat it does
🔄 New SearchReload the page and start a fresh scan
📋 Copy (N)Copy selected filenames to clipboard. N = count selected.
📂 Move (N)Move selected files or stage them in the Move Queue
🗑️ Delete (N)Delete selected files or stage them in the Delete Queue
✕ Deselect AllRemove selection from all cards
⚖️ Compare (N)Open the compare modal for Ctrl+clicked files. Needs 2+.
🔇 VideosToggle mute/unmute for all video cards
Queue Mode checkboxWhen checked: stage files for review before executing. Recommended.
Fast Mode checkboxUse EXIF thumbnail for JPEG scanning — much faster. On by default.
Scan Images checkboxInclude or exclude image files from the scan
Scan Videos checkboxInclude or exclude video files from the scan
Similarity Threshold sliderMaximum Hamming distance for grouping. Lower = stricter. Re‑clusters on release.
Click cardSelect / deselect the file
Ctrl + Click cardAdd / remove from compare list (purple border)
Click & drag (empty area)Box‑select multiple cards at once
Ctrl + dragAdd to existing selection with box
Right‑click cardContext menu: Copy / Move / Delete / Compare
🔍 hover iconOpen full‑size preview with metadata and action buttons
Hover video cardAuto‑play the video clip

⭐ What Users Say

Based on 215 reviews

"pHash found duplicates that other tools completely missed — re‑compressed JPEGs, watermarked versions, even photos that had been resized and colour‑corrected. The DCT approach is genuinely impressive."

"I've tried every duplicate finder out there and pHash is the only one that consistently finds all my duplicates across different formats and quality levels. The Compare modal with similarity percentages is incredibly useful."

"I manage a large photo archive and pHash is my go‑to algorithm. It catches subtle duplicates that aHash and dHash miss, and the false positive rate is much lower than BlockHash. A fantastic all‑rounder."

"The DCT-based hashing is brilliant. I scanned 15,000 images and found duplicates that had been through multiple rounds of compression and resizing. pHash grouped them perfectly at the default threshold."

💡 Tips for Best Results

Back Up First

Always back up your files before deleting anything. Deleted files bypass the recycle bin and cannot be recovered.

pHash Is Your All‑Rounder

For a general photo collection where you want to catch re‑saved, re‑compressed, or lightly edited duplicates with minimal false positives, pHash is often the best first choice.

Trust the Default Threshold

The default of 10 is well‑calibrated for pHash's 64‑bit hash space. Try it before adjusting. Lower it if you want only very close matches; raise it if you know edited copies exist.

Use Compare for Borderline Groups

Ctrl+Click two cards then click Compare to see side‑by‑side with a similarity percentage. pHash's frequency‑domain similarity % is a good indicator of how perceptually similar two images really are.

Move, Don't Delete

Use Move to a “Sakarto‑Duplicates” folder rather than deleting outright. Review the moved files for a few days before permanently removing anything.

Combine Algorithms Strategically

Run pHash for general deduplication, then use dHash for brightness‑adjusted copies pHash might miss, and ORB for rotated images. Each algorithm catches a different class of duplicates.

⚠️ Known Limitations

Not rotation‑invariant.

Rotating an image 90° changes the positions of all DCT coefficients significantly. A rotated copy will not be matched at any threshold. For rotation‑tolerant matching, use ORB Feature Matching.

Colour is not compared — only luminance.

Like all other hash algorithms in Sakarto, pHash converts to grayscale before processing. A full‑colour version and a desaturated version of the same image may produce identical or near‑identical hashes. If colour fidelity matters, use Color Signature.

Slightly slower than simple hash algorithms.

The 2D DCT computation on a 32×32 matrix is more expensive than the pixel comparisons in aHash or dHash. For most collections the difference is negligible, but very large folders may take noticeably longer. Fast Mode mitigates this significantly for JPEG‑heavy libraries.

No undo for file deletion.

The File System Access API bypasses the OS recycle bin. Always use Queue Mode to stage and review before executing.

Video scanning pauses when you switch tabs.

Browsers throttle background video decoding. Video processing pauses when the tab is hidden and resumes when you return. Image hashing (in the Web Worker) continues at full speed regardless.

Move and Delete require Chrome or Edge.

The File System Access API is available only in Chrome 86+ and Edge 86+. Firefox and Safari can scan and display results but cannot move or delete files.

🔒 Privacy & Security

Zero network activity after page load. Open DevTools → Network tab and verify: no outbound requests during any scan, hash computation, or file operation.
No accounts, no cookies, no analytics. The only localStorage data saved is your OS detection and checkbox preferences. No file names, paths, or hashes are ever saved or transmitted.
Folder access is scoped and session‑only. Permission is granted only for the specific folder you select, lasts only while the tab is open, and is revocable at any time from browser site settings.
Purely static — no backend. Sakarto is HTML, CSS, and JavaScript. There is no server, no database, and no API receiving your data.

❓ Frequently Asked Questions

How is pHash different from aHash, dHash, BlockHash, and wHash?
All five produce a binary hash compared with Hamming distance, but they capture different image properties. aHash compares pixels to the mean — fast but coarse brightness layout. dHash compares adjacent pixels to encode brightness gradient directions — good for exposure‑adjusted copies. BlockHash averages blocks and compares to the median — noise‑tolerant but coarse. wHash applies a Haar Wavelet Transform — similar quality to pHash at lower cost. pHash applies a Discrete Cosine Transform to a 32×32 canvas and extracts the top‑left 8×8 block of low‑frequency coefficients. DCT is the same mathematical operation used in JPEG compression: those low‑frequency coefficients represent the fundamental structure of the image, not fine detail. Re‑compression, format conversion, mild sharpening, light colour grading, and watermarking all affect high‑frequency detail without touching the low‑frequency structure — which is why pHash is the most stable of the hash algorithms across image edits.
Two clearly different photos are being grouped together. How do I fix it?
Lower the similarity threshold slider to 4–8. Two photos with very similar structural composition — same type of scene, similar lighting, similar subject placement — can produce similar low‑frequency DCT patterns even if they're different photos. pHash is more discriminating than aHash or BlockHash, but composition‑level similarities can still cause false positives at loose thresholds. Use the Compare modal (Ctrl+Click two cards, then Compare) to verify before acting. If false positives persist even at strict thresholds, try Color Signature, which also compares colour distribution and can distinguish structurally similar photos with different colour palettes.
I know two files are duplicates but pHash isn't grouping them. What should I try?
First, raise the threshold toward 15–20. Second, check aspect ratios — pairs differing by more than 10% are excluded before hashing. Third, consider the type of edit: pHash handles re‑compression, format conversion, mild colour grading, and watermarking well, but fails on rotation (try ORB), heavy cropping that removes more than ~30% of the image (structural content shifts too much), or very dramatic brightness changes that clip large areas (try dHash for exposure‑adjusted copies). Fourth, confirm both files decode successfully — a corrupted image will produce a garbage hash.
Why is pHash more stable across JPEG re‑compression than aHash?
JPEG compression works by applying a DCT to the image and discarding small high‑frequency coefficients. aHash downscales to 16×16 and compares individual pixel values — those pixel values change slightly each time JPEG is re‑compressed because the encoder reconstructs them from the stored (and partially discarded) DCT data. pHash directly computes the DCT and extracts the low‑frequency coefficients, which are the ones JPEG keeps most accurately. So re‑compressing a JPEG barely changes pHash's input data, while it does affect the pixel values that aHash reads.
What does Fast Mode do for pHash, and should I leave it on?
Fast Mode reads the EXIF‑embedded thumbnail in JPEG files (usually around 160×120 pixels) rather than decoding the full image. Since pHash works on a 32×32 canvas anyway, the thumbnail is more than large enough and produces an identical hash in the vast majority of cases. Leave Fast Mode on. The only reason to turn it off is if you notice groupings on JPEG files that disappear when Fast Mode is off, suggesting the EXIF thumbnails in those files were stripped or corrupted by an image editor.
Can pHash find a watermarked version of my photo?
Usually yes — this is one of pHash's strengths. A watermark adds detail to the image (typically text or a logo overlay), which is inherently high‑frequency content. pHash only uses the low‑frequency DCT coefficients, which represent the broad structure of the image. As long as the watermark doesn't cover such a large area that it fundamentally changes the image's structural layout, pHash will still group the watermarked and original versions. At the default threshold of 10, medium‑opacity watermarks in corners or along edges are typically ignored entirely.
Why does video scanning pause when I switch tabs?
Browsers throttle video element processing when a tab is hidden to conserve battery and CPU. Sakarto detects this via the Page Visibility API and pauses video frame extraction, resuming automatically when you return. Image hashing runs in a background Web Worker, which is not throttled by tab visibility — images keep processing at full speed in the background.
Can I recover files after deleting them?
No. The File System Access API's remove() method permanently deletes files without going through the OS Recycle Bin or Trash. Queue Mode is on by default to prevent accidents: files are staged for review before any deletion is executed. Verify each group using the preview icon and Compare modal before acting. When in doubt, use Move to a “Sakarto‑Duplicates” subfolder instead of Delete — you can always delete from there later.
What file types are supported?
Images: JPEG, PNG, GIF, WebP, BMP. Videos: MP4, WebM, MOV, MKV. Files over 40 MB are silently skipped. HEIC/HEIF, SVG, RAW formats, and TIFF are not supported because browsers cannot natively decode them. Convert RAW or HEIC files to JPEG or PNG first.
Does this work on Firefox or Safari?
Scanning, DCT computation, result display, and the Compare modal all work in Firefox and Safari. Move and Delete require the File System Access API, available only in Chrome 86+ and Edge 86+. In other browsers, scan, review results in the Compare modal, and use Download List to export a report for manual file management.