Everything you need, nothing inflated.
Take any of this verbatim. Every number below is reproducible from the repository, and the list of things not to write is as important as the list of things to write.
The one-liner
ScrubPony strips identifying metadata out of JPEG files without altering a single pixel.
The one-paragraph version
A photo off your phone carries GPS coordinates accurate to a few metres, the capture time, the device serial, and often an uncropped thumbnail of what you cropped out. ScrubPony is a command line tool that removes all of it and provably does not touch the image: everything from the JPEG's SOS marker to the end of the file is copied through verbatim. It is written in C99 against POSIX.1-2008 with no dependencies beyond libc, runs on macOS and Linux, and is MIT-licensed at github.com/norsehorse-dev/ScrubPony.
Facts
| Item | Detail |
|---|---|
| Name | ScrubPony (project); scrubpony (binary, lowercase) |
| Version | 1.0.0 |
| Licence | MIT |
| Developer | NorseHorse, a solo independent developer |
| Repository | github.com/norsehorse-dev/ScrubPony |
| Website | scrubpony.app |
| Contact | NorseHorse@norsehor.se |
| Platforms | macOS and Linux. BSD untested. Windows out of scope by design. |
| Formats | JPEG only |
| Language | C99, POSIX.1-2008, no dependencies beyond libc |
| Price | Free |
Figures
| Claim | Detail |
|---|---|
| Size | 2,251 lines of C (non-blank, non-comment, src/), against a test suite with more lines in it than the program |
| Test suite | 741 checks across 7 test binaries, plus 8 integration suites |
| Sanitizers | Every test binary runs under AddressSanitizer and UndefinedBehaviorSanitizer |
| Warnings | Zero under -Wall -Wextra -Wpedantic -Wconversion, gcc and clang, both platforms |
| Fuzzing | 7,575,421 libFuzzer executions, zero crashes, zero leaks |
| Atomicity | 30 SIGKILLs mid-write on a 24 MB file; zero partial files |
| Independent check | 13/13 fixtures agree with exiftool on segment structure and orientation |
| Throughput | 1,200-file nested library in 3.2 s; in place 2.9 s |
| Verified on | macOS 26.5.2 arm64 (Apple clang 21); Linux aarch64 and x86-64 (gcc 11–13, clang 18) |
CI runs the full suite on both platforms with both compilers on every push, plus a timed libFuzzer job.
The angles worth taking
- The marker code never decides.
APP1is EXIF or XMP;APP2is an ICC colour profile or an MPF block that can hold an entire second photograph. One of each pair is kept and the other dropped, and only the identifier string tells them apart. Getting that wrong is how a naive scrubber either wrecks your colours or silently leaves behind the coordinates it promised to remove. - It fails closed. Unrecognised
APPnsegments are dropped by default, because an undocumented vendor segment is exactly where a manufacturer parks a serial number. - Your portrait photos do not come out sideways. Phones do not rotate pixels; they record an EXIF orientation tag. Drop EXIF and that instruction goes with it, which is why most metadata strippers leave you a folder of sideways photographs. ScrubPony writes back a minimal 36-byte block containing exactly one field.
- Losslessness is provable, not asserted. The test suite verifies it four ways and deliberately locates the SOS offset with an independent scanner rather than asking ScrubPony where it thinks the scan starts.
- It tells you what it found. The line people react to is
257 carried GPS coordinates.
Do not write
This is a privacy tool, and overclaiming about one is worse than underselling it. Please avoid:
- Not "removes all metadata from any image." It handles JPEG only. PNG, HEIC, RAW, TIFF and video are out of scope today.
- Not "anonymises your photos." It removes container metadata. It cannot touch anything encoded in the pixels — invisible watermarks, a reflection in a window, a visible street sign.
- Not "Windows support." Out of scope by design; the safety guarantees rest on POSIX semantics that differ there.
- BSD is untested, not unsupported. Please word it that way.
-iloses extended attributes (Finder tags, Spotlight comments, quarantine flags) and breaks hard links, because replacing a file installs a new inode. This is documented, not hidden.- The mtime is deliberately reset — it is metadata too. Readers are surprised by this, so lead with it rather than let them discover it.
- ICC colour profiles are kept by default (dropping them shifts colour).
--strictdrops them. Please do not imply the default is maximum paranoia. - Please do not invent a rating, an audit, a user count, or a roadmap commitment. None exist.
Sample output
Real, and safe to reproduce:
$ scrubpony -r -d ~/clean ~/Pictures scrubpony: 834 scrubbed, 366 already clean, 3 not JPEG, 4 skipped, 2 failed scrubpony: 1148605 bytes of metadata removed scrubpony: 257 carried GPS coordinates scrubpony: 266 rely on EXIF orientation to display correctly (266 preserved)
Assets
Use freely when writing about ScrubPony.
Accent colour #9d7cf5. Capitalisation: the project is ScrubPony, the binary is lowercase scrubpony. Keep that split — nobody wants a capital letter in a shell command.
The family
ScrubPony is one of seven tools by the same developer, all following the same rules: no accounts, no tracking, inspectable code. The others are listed here.
Questions
One developer, one inbox: NorseHorse@norsehor.se. Happy to answer technical questions on the record, and happy to be told a claim on this page is too strong.