Lightweight, privacy‑first face anonymization in the browser. Drop an image, auto‑detect faces (with manual tweaks), then blur / pixelate / color‑block them. Nothing ever uploads.
- 100% client‑side (no image leaves the device)
- Face detection + manual box add/remove
- Three anonymization modes: Blur, Pixelate, Color Block
- Adjustable intensity / pixel size
- EXIF stripped on download
- Multi‑language UI (EN, PL)
- Live global counters (images processed / faces anonymized)
- Zoom & pan canvas + manual box drawing
- Accessible UI (keyboard focusable controls)
| Area | Tech |
|---|---|
| Framework | React + TypeScript (Vite) |
| UI | Tailwind CSS, shadcn-ui, Radix primitives |
| State | Zustand + localStorage persistence |
| Detection | TensorFlow.js (BlazeFace / Face Detection) |
| Build | Vite + SWC React plugin |
| Backend (counters only) | Tiny PHP endpoint + JSON file |
git clone <REPO_URL> noface
cd noface
npm install
npm run dev
# open http://localhost:5173Production build:
npm run build
npm run preview # http://localhost:4173- Image is loaded into an HTMLCanvasElement
- Face detection model returns bounding boxes
- User can toggle/select or draw new boxes (coordinates adjusted for zoom/pan transforms)
- Chosen anonymization algorithm mutates pixel regions (blur, pixelate, or fill color)
- Canvas is exported to a re‑encoded image (eliminates EXIF metadata)
Currently shipping English (en) and Polish (pl). Translations live in src/i18n/index.tsx.
To add a new language (community PRs welcome):
- Add locale code to the
Localeunion - Add dictionary block with string keys mirroring
en - Add to exported
localesarray for the selector - Submit PR including translation credit in the PR description
Usage example:
const { t } = useI18n();
<h1>{t('hero.tagline')}</h1>The app dispatches window events for optimistic counters:
noface:imagedetail: { images: 1, faces: 0 }noface:anonymizeddetail: { images: 0, faces: }
LiveCounters listens and merges them with server totals (polled every 5s).
src/
components/
ImageProcessor.tsx # detection + anonymization UI
FileDropzone.tsx # upload + validation
LiveCounters.tsx # polling + optimistic updates
LanguageSelector.tsx # locale switcher
i18n/ # translations + provider
utils/ # image & face helpers
store/ # zustand state
pages/ # routed pages (Home, Terms, Privacy)
public/api/counter.php # simple JSON counter service
- Change polling interval:
COUNTER_POLL_INTERVALinLiveCounters.tsx - Add anonymization modes: extend logic in
imageProcessing.ts - Edit CSP / meta:
index.html
- Gradient text uses sufficient contrast backgrounds
- Tab focus retained on interactive elements
- Semantic button usage for actions
- Batch processing (multi‑image queue)
- Box edge refinement (smart padding)
- Drag to reposition existing boxes
- Optional download quality selector
- Service worker for offline usage
See SECURITY.md for reporting guidelines. No external image uploads occur; any discovered data exfil path is high severity.
See MODEL-LICENSES.md for bundled model attribution (BlazeFace, MediaPipe). Apache 2.0 notices are aggregated in NOTICE.
Maintained by Łukasz Kosma (Alien)
GitHub: https://github.com/pearpl
Website: https://www.pear.pl
If this project saved you time or helped protect privacy you can support development:
Funds help cover maintenance, new features, performance work, and additional privacy tooling.
MIT. See LICENSE for full text.
Happy anonymizing! Contributions & improvements welcome.
