A Chrome extension that detects AI-generated and manipulated images in real time,
explains every finding in plain English, and cross-checks claims against live fact-check data.
Built for Next Byte Hacks V2 by Harsh Bhanushali.
| Link | Description | |
|---|---|---|
| 🏠 | pixelproof.dualmindlab.tech | Full landing page — overview, features, screenshots |
| 🎬 | pixelproof.dualmindlab.tech/#demo | Interactive demo — no API keys required |
| 🏆 | devpost.com/software/pixelproof-l5ofpx | Hackathon submission page — Next Byte Hacks V2 |
Note — Demo runs in Fallback Mode by default. You will see the complete detection flow — overlays, confidence scores, plain-English explanations, and the verdict panel — without needing any API key. To enable live AI detection, install the extension locally and add your own keys (see API Key Setup).
The internet is drowning in AI-generated images, deepfakes, and manipulated media — and most people have no way to tell.
In 2024, AI-generated images spread as "real" news across every major platform. Synthetic faces passed as real people. Fabricated war footage shaped public opinion. Deepfaked politicians went viral before corrections could catch up. The average user scrolling their feed has zero tools to push back — in the moment, in context, without leaving the page.
Existing solutions ask users to copy a URL into a third-party tool. By then, the damage is done.
PixelProof takes a different approach:
❌ Old way: See image → feel unsure → maybe Google it → probably forget it
✅ PixelProof: See image → scan in 1 click → instant verdict + explanation → right there
It lives in your browser. It works on every page. It catches fakes while you scroll.
| Feature | What It Does | Why It Matters |
|---|---|---|
| 🖼️ Live Image Scanning | Detects AI-generated or manipulated images on any webpage without leaving the tab | No context switching — detection happens where the content is |
| 🤖 AI-Powered Explanation | Google Gemini translates raw detection output into plain English | Non-technical users can understand and act on the verdict |
| 📰 Fact-Check Lookup | Cross-references image claims against Google's Fact Check database | Surfaces existing debunks automatically |
| ⚡ Smart Caching | Results stored in chrome.storage.local — rescans return instantly |
Zero duplicate API calls; instant UX on repeat visits |
| 🛡️ Graceful Fallback | Works even when all APIs are down — UI never breaks | Demo-safe; field-reliable |
| 🔑 Local Key Storage | API keys live in chrome.storage.local only |
Keys never leave your machine, never touch any server |
| 🎯 Bulk Scanning | Scan all images on a page in a single click | Efficient for news pages, social feeds, image galleries |
| 🎨 DOM Overlays | Visual confidence badges appear directly over each scanned image | At-a-glance trust signals without opening any panel |
| 📊 Slide-In Panel | Detailed verdict, Gemini explanation, and fact-check results in one place | Full context without disrupting the page layout |
DevTools recommended for the full demo experience (service worker console, storage inspection).
PixelProof is built on a 4-layer pipeline inside Chrome's Manifest V3 architecture. Each layer has a single responsibility, communicates over Chrome's native messaging bus, and can fail independently without taking down the rest of the system.
User Action ──▶ Content Script ──▶ Background Worker ──▶ External APIs
↕
Chrome Storage Cache
The diagram below shows all components and how they connect:
flowchart LR
U[👤 User] --> P[Popup UI]
U --> C[Content Script]
P --> C
C --> B[Background Service Worker]
B --> R[Reality Defender API]
B --> G[Gemini AI API]
B --> F[Google Fact Check API]
B --> S[Chrome Storage Cache]
B --> O[Options Page]
O --> K[chrome.storage.local]
K --> B
style U fill:#1e293b,color:#f8fafc
style P fill:#334155,color:#f8fafc
style C fill:#334155,color:#f8fafc
style B fill:#7c3aed,color:#fff
style R fill:#ef4444,color:#fff
style G fill:#1a73e8,color:#fff
style F fill:#34a853,color:#fff
style S fill:#f59e0b,color:#111
style O fill:#334155,color:#f8fafc
style K fill:#f59e0b,color:#111
Component responsibilities:
| Component | Role |
|---|---|
| Popup UI | Extension dashboard — triggers scans, renders results, opens settings |
| Content Script | Runs on every page — discovers images, injects DOM overlays, relays messages |
| Background Service Worker | Orchestrates the full scan pipeline, manages the cache, handles API calls |
| Chrome Storage Cache | Persists scan results per image URL — eliminates duplicate API requests |
| Options Page | Lets users save API keys securely to chrome.storage.local |
| Reality Defender API | Classifies each image as real, AI-generated, or manipulated with a confidence score |
| Gemini AI API | Converts the raw detection verdict into a plain-English explanation |
| Google Fact Check API | Queries a live fact-check database for claims related to the image |
The scan sequence diagram shows the exact message flow from the moment a user clicks Scan to the moment the verdict appears on screen:
sequenceDiagram
participant User
participant Popup
participant Content as Content Script
participant BG as Background Worker
participant RD as Reality Defender
participant GM as Gemini AI
participant FC as Google Fact Check
User->>Popup: Click "Scan All Images"
Popup->>Content: sendMessage(scanAllImages)
Content->>BG: send image payload (src / base64)
BG->>BG: check chrome.storage cache
alt ✅ Cache Hit
BG-->>Content: return cached result instantly
else ❌ Cache Miss
BG->>RD: POST image for AI detection
alt RD Success
RD-->>BG: verdict + confidence score
BG->>GM: "explain this verdict in plain English"
GM-->>BG: human-readable explanation
BG->>FC: search related claims
FC-->>BG: matching fact-checks
BG->>BG: store full result in cache
else RD Fails (network / API down)
BG->>BG: log diagnostics to service worker
BG->>BG: generate simulated fallback verdict
end
end
BG-->>Content: full result payload
Content-->>Popup: update UI with verdict + overlay
Step-by-step breakdown:
- User clicks Scan — the popup sends a message to the content script running on the active tab.
- Content script collects images — it discovers all
<img>elements (and canvas-derived base64 payloads) and forwards them to the background worker. - Background worker checks the cache — if a result already exists for that image URL, it returns immediately. No API call needed.
- Reality Defender call — on a cache miss, the image is POSTed to Reality Defender's detection endpoint. The response includes a verdict label and a confidence percentage.
- Gemini enrichment — the raw verdict is sent to Gemini with a prompt to produce a human-readable explanation suited to a non-technical audience.
- Fact-Check lookup — the background worker queries Google's Fact Check API for any claims that match the image context.
- Result assembly & cache write — all three API responses are merged into a single result object and written to
chrome.storage.local. - UI update — the content script receives the result and renders a confidence overlay on the image; the popup renders the full verdict panel.
Each image scan moves through a well-defined set of states. The diagram shows every valid transition:
stateDiagram-v2
[*] --> Idle : Extension loaded
Idle --> Scanning : User clicks Scan
Scanning --> CacheHit : Result found in storage
Scanning --> APIRequest : Cache miss → call Reality Defender
CacheHit --> Display : Return immediately
APIRequest --> Enrich : Reality Defender returns verdict
APIRequest --> Fallback : Network / API failure
Enrich --> Enrich : Gemini explanation in progress
Enrich --> Enrich : Fact Check lookup in progress
Enrich --> Display : All three API responses assembled
Fallback --> Display : Simulated verdict generated locally
Display --> Idle : User closes popup or dismisses overlay
Display --> Scanning : User triggers rescan
State definitions:
| State | Description |
|---|---|
| Idle | Extension is loaded and waiting. No scan in progress. |
| Scanning | Image payload received; cache lookup underway. |
| CacheHit | A valid cached result was found. Display immediately — no API call. |
| APIRequest | Cache miss; Reality Defender detection request is in flight. |
| Enrich | Verdict received; Gemini and Fact Check requests are in flight in parallel. |
| Fallback | One or more API calls failed; simulated verdict generated locally. |
| Display | Final result (live or fallback) rendered in the overlay and verdict panel. |
The data flow diagram traces how raw image bytes become a structured, cached result object:
flowchart TD
IMG[🖼️ Image on Page] --> CS[Content Script\nextract src / canvas base64]
CS --> BW[Background Worker]
BW --> CACHE{Cache Check}
CACHE -- ✅ Hit --> RESULT[Result Object]
CACHE -- ❌ Miss --> RD[Reality Defender\nPOST /scan]
RD --> VERDICT[verdict + confidence score]
VERDICT --> GEM[Gemini\ngenerate plain-English explanation]
GEM --> EXP[Human-Readable Explanation]
EXP --> FC[Google Fact Check\nquery related claims]
FC --> CLAIMS[Matched Claim Results]
CLAIMS --> ASSEMBLE[Assemble Full Result Object]
ASSEMBLE --> STORE[Write to chrome.storage.local]
STORE --> RESULT
RESULT --> UI[🎨 Popup + DOM Overlay UI]
style IMG fill:#1e293b,color:#f8fafc
style CACHE fill:#f59e0b,color:#111
style RD fill:#ef4444,color:#fff
style GEM fill:#1a73e8,color:#fff
style FC fill:#34a853,color:#fff
style RESULT fill:#7c3aed,color:#fff
style UI fill:#0f172a,color:#f8fafc
Result object schema (simplified):
{
"imageUrl": "https://example.com/image.jpg",
"verdict": "AI_GENERATED",
"confidence": 0.94,
"explanation": "This image shows unnatural texture uniformity around the hairline and ears — a common artifact in GAN-generated portraits...",
"factChecks": [
{
"claim": "Photograph shows world leader at press conference",
"rating": "FALSE",
"source": "Associated Press Fact Check",
"url": "https://apnews.com/..."
}
],
"cachedAt": 1718000000000
}pixelproof/
│
├── 📄 manifest.json # MV3 manifest — permissions, service worker declaration
├── 📄 background.js # Scan orchestration, API calls, cache management, tab messaging
├── 📄 content.js # Image discovery, DOM overlay injection, per-image badge UI
├── 🎨 styles.css # Shared content-script styles (overlays, badges)
├── 📄 config.example.js # API key template — copy to config.js (gitignored)
├── 📄 .env.example # Environment variable template for key injection script
│
├── 📂 popup/
│ ├── popup.html # Extension dashboard — main UI shell
│ ├── popup.js # Scan trigger, result renderer, panel coordinator
│ └── popup.css # Dashboard layout and component styles
│
├── 📂 options/
│ ├── options.html # API key settings page
│ └── options.js # chrome.storage.local key management
│
├── 📂 panel/
│ ├── panel.html # Slide-in full verdict panel
│ ├── panel.js # Panel interactions, share actions, event listeners
│ └── panel.css # Glassmorphism panel layout and animation
│
├── 📂 utils/
│ ├── api.js # Reality Defender + Gemini + Fact Check API wrappers
│ ├── cache.js # Storage-backed result cache (get, set, invalidate)
│ └── dom.js # Image discovery helpers and overlay DOM utilities
│
├── 📂 scripts/
│ └── generate_config.js # .env → config.js key injection for local development
│
├── 📂 assets/
│ ├── logo_Custom_1.png # Official PixelProof logo (hosted at i.ibb.co)
│ └── icons/ # Extension icon set (16×16, 48×48, 128×128)
│
├── 📂 docs/
│ ├── imp.md # Implementation notes
│ ├── master.md # Master reference document
│ └── prd_extracted.txt # Extracted product requirements
│
├── 📄 DEMO_CHECKLIST.md # Recorder-friendly presentation order and timing notes
├── 📄 CONTRIBUTING.md # Contribution guide — branching, PRs, code style
├── 📄 SECURITY.md # Vulnerability reporting and secret-handling policy
├── 📄 LICENSE # MIT License
├── 📄 package.json # Minimal npm metadata for development scripts
└── 📄 README.md # This file
Zero runtime dependencies. PixelProof ships as pure HTML/CSS/JS — no bundler, no framework, no node_modules in the extension package.
- Google Chrome 109+ or Microsoft Edge 109+ (desktop)
- Git
- Node.js ≥ 18 (only required if you use the
generate_config.jskey injection script) - API keys for live detection (optional — Fallback Mode works without them)
git clone <your-repository-url>
cd pixelproof- Open
chrome://extensionsin Chrome or Edge - Enable Developer mode (toggle in the top-right corner)
- Click Load unpacked
- Select the
pixelproof/directory you just cloned - Confirm the PixelProof icon appears in your toolbar
No build step required. The extension loads directly from source.
- Navigate to any image-heavy page (a news site works well)
- Click the PixelProof icon in the toolbar
- Click Scan All Images
- Overlays appear on each image — click any flagged one for the full verdict
That is the complete setup for Fallback Mode. To enable live AI detection, continue to API Key Setup.
Option A — Settings Page (recommended for most users)
- Click the PixelProof toolbar icon
- Open Settings (gear icon)
- Paste each key into its field
- Click Save
- Reload the extension if prompted
Option B — Config File (for developers)
# 1. Copy the example environment file
cp .env.example .env
# 2. Open .env and fill in your keys
# REALITY_DEFENDER_API_KEY=your_key_here
# GEMINI_API_KEY=your_key_here
# FACT_CHECK_API_KEY=your_key_here
# 3. Generate the runtime config
node scripts/generate_config.js
# 4. Reload the extension in chrome://extensions| Key | Provider | Link | Cost |
|---|---|---|---|
REALITY_DEFENDER_API_KEY |
Reality Defender | realitydefender.com | Contact for access |
GEMINI_API_KEY |
Google AI Studio | ai.google.dev | Free tier available |
FACT_CHECK_API_KEY |
Google Cloud Console | console.cloud.google.com | Free tier available |
Privacy guarantee: Keys are stored exclusively in
chrome.storage.local. They are never transmitted to any server, never bundled into the extension package, and never appear in logs. Both.envandconfig.jsare listed in.gitignore.
No API keys required — Fallback Mode is on by default. You can also run the demo at pixelproof.dualmindlab.tech/#demo.
| Step | Action | What You See |
|---|---|---|
| 1 | Open any news or social media page with multiple images | Normal page |
| 2 | Click the PixelProof icon in the Chrome toolbar | Dashboard popup opens |
| 3 | Click Scan All Images | Detection overlays appear on every image in real time |
| 4 | Click a flagged image | Slide-in panel shows verdict, confidence score, Gemini explanation, and matching fact-checks |
| 5 | Refresh the page and scan the same image again | Result returns instantly from cache — no API call |
| 6 | Open Settings | Inspect local API key storage; keys visible only to you |
| 7 | Clear a key and scan again | Fallback Mode activates — UI continues working normally with simulated verdict |
For a structured presenter flow with exact timing, see
DEMO_CHECKLIST.md.
// Sent from popup.js to content.js via Chrome messaging
chrome.tabs.sendMessage(tabId, {
action: "scanImage",
imageUrl: "https://example.com/suspicious-photo.jpg"
}, (result) => {
console.log(result.verdict); // "AI_GENERATED"
console.log(result.confidence); // 0.94
console.log(result.explanation); // "This image shows..."
});// From background.js — checks if a result is already stored
import { getCache } from "./utils/cache.js";
const cached = await getCache("https://example.com/image.jpg");
if (cached) {
console.log("Cache hit:", cached.verdict);
} else {
console.log("Cache miss — triggering full scan");
}# Inject your API keys into config.js for the extension runtime
node scripts/generate_config.js
# Expected output:
# ✅ config.js written — reload the extension in chrome://extensions# Test general internet connectivity
Invoke-WebRequest -Uri 'https://www.google.com/generate_204' -UseBasicParsing
# Test Reality Defender endpoint reachability
Invoke-WebRequest -Uri 'https://api.realitydefender.com/' -UseBasicParsing| Metric | Value | Notes |
|---|---|---|
| Cold scan (cache miss) | ~1.8 – 3.5s | Depends on Reality Defender + Gemini response times |
| Warm scan (cache hit) | < 50ms | Served from chrome.storage.local synchronously |
| Bulk scan — 10 images | ~4 – 8s | Requests are dispatched in parallel |
| Extension load time | < 100ms | No bundler overhead; pure JS |
| Storage per result | ~2 – 5 KB | Full result object including explanation text |
| API call deduplication | 100% | Each unique image URL is scanned at most once per cache lifetime |
Benchmarks recorded on Chrome 124, MacBook Pro M2, 100 Mbps connection. Network latency is the dominant variable.
PixelProof is demo-safe by design. No API key, no network, no problem.
API key missing ──▶ fallback triggered
Network failure ──▶ fallback triggered
API timeout ──▶ fallback triggered
When fallback mode activates:
- The service worker logs a diagnostic message to the extension console
- A simulated verdict is generated locally with realistic confidence scores and label categories
- All UI components continue to render — overlays, explanations, confidence scores, the full verdict panel
- The user sees a small
[Demo]indicator on the verdict, clearly marking the result as simulated
To trigger fallback mode intentionally:
- Open Settings
- Clear any one API key
- Scan an image
- The extension detects the missing key and routes to fallback immediately
Fallback mode is intentional, not a workaround. It ensures PixelProof is useful in constrained environments and that demos never break mid-presentation.
- Browser-native image scanning on any page
- Reality Defender → Gemini → Fact Check 3-API orchestration pipeline
- Intelligent caching layer with
chrome.storage.local - DOM overlay badges with confidence scores
- Slide-in verdict panel with full explanation and fact-checks
- Graceful fallback mode for offline / keyless usage
- Secure local API key management via the Options page
- Bulk scan (all images on a page) with one click
- Chrome Web Store listing
- Video/GIF frame detection (scan embedded media)
- Right-click context menu — "Check this image with PixelProof"
- Badge colour theming (accessible high-contrast mode)
- Export scan report as PDF
- Firefox and Edge Web Store support
- On-device lightweight model for zero-latency pre-screening
- Shareable verdict links (privacy-respecting, URL-hashed)
- Community flagging layer — crowdsourced confirmation signals
- Integration with browser Reading Mode for distraction-free fact-checking
Contributions toward any roadmap item are welcome — see Contributing.
- Open a news or social media page with multiple images
- Scan a single image via the overlay badge button
- Scan all images via the popup — verify overlays appear across the page
- Click a flagged image — verify the full verdict panel opens with explanation and fact-checks
- Refresh the page and rescan — confirm instant cache return (< 50ms)
- Clear the cache in
chrome://extensions→ Storage → then rescan to confirm a fresh API call fires
- Remove one API key in Settings → verify fallback mode activates and UI remains fully functional
- Disconnect network → verify diagnostics appear in the service worker console (open via
chrome://extensions→ PixelProof → service worker link) - Navigate to a page with cross-origin images → observe canvas tainting behaviour and error handling
- Load a page with zero images → verify the popup handles the empty state gracefully
Invoke-WebRequest -Uri 'https://www.google.com/generate_204' -UseBasicParsing
Invoke-WebRequest -Uri 'https://api.realitydefender.com/' -UseBasicParsing- Go to
chrome://extensions - Find PixelProof → click service worker link
- Open the Console tab
- Run a scan — all log lines from
background.jsappear here
The extension icon doesn't appear in my toolbar after loading unpacked.
Click the Extensions puzzle icon in the Chrome toolbar → find PixelProof in the list → click the pin icon to pin it to the toolbar.
Scanning returns no results on some pages.
Some pages serve images from cross-origin domains with strict CORS headers. The browser's canvas security model prevents PixelProof from reading pixel data for those images. The extension logs a CORS_TAINT diagnostic to the service worker console when this happens. As a workaround, try scanning images that are served from the same origin as the page, or use the file-upload path if available.
All scans return "Demo" / fallback verdicts even though I added my keys.
After saving API keys in the Options page, reload the extension in chrome://extensions. The service worker needs to restart to pick up the new values from chrome.storage.local. If the issue persists, open the service worker console and look for any key-read errors.
The scan is slow on the first run.
Cold scans depend on network round-trips to Reality Defender and Gemini. On a standard connection, expect 1.8 – 3.5 seconds. Subsequent scans of the same image return from cache in under 50ms.
Can I use PixelProof on mobile?
Chrome extensions are not supported on Chrome for Android or iOS. PixelProof requires a desktop Chromium browser (Chrome or Edge 109+).
Is my browsing history or image data sent anywhere?
Only the images you actively choose to scan are sent — and only to the three declared API providers (Reality Defender, Google Gemini, Google Fact Check). Your API keys never leave your machine. No analytics, no telemetry, no third-party tracking.
How do I report a false positive or false negative?
Reality Defender's detection model determines the verdict. For systematic errors, consider reporting the case directly to Reality Defender. For bugs in the extension workflow, open an issue following the process in CONTRIBUTING.md.
| Practice | Implementation |
|---|---|
| Key isolation | API keys stored exclusively in chrome.storage.local — never in source code, never in network requests beyond the designated API endpoint |
| No key bundling | .env and config.js are in .gitignore — they are never committed or included in the extension package |
| Minimal permissions | manifest.json declares only the permissions strictly required (see the manifest for the full list) |
| No telemetry | PixelProof makes zero outbound requests except to the three declared API providers |
| Transparent fallback | When APIs fail, the extension clearly marks results as simulated rather than silently presenting them as live |
If you discover a security vulnerability, please follow the responsible disclosure process in SECURITY.md. Do not open a public issue. If a key is accidentally exposed, rotate it immediately at the issuing provider.
PixelProof is a practical triage tool — not a legally authoritative verdict system.
- CORS restrictions — Cross-origin images may be blocked by browser canvas security rules. The extension cannot read pixel data for images that set strict CORS headers.
- Detection accuracy — Verdict accuracy depends on Reality Defender's model. No AI detection system is infallible; treat verdicts as signals, not ground truth.
- Fallback mode is simulated — Results produced in Fallback Mode are not live detections. They are clearly labelled with a
[Demo]indicator. - No video support — PixelProof analyses still images only. Embedded video, GIF, and canvas animations are not supported in v1.0.
- Desktop only — Chrome extensions are unavailable on mobile browsers.
- No page modification — PixelProof adds overlays but never blocks, removes, or replaces images. Verdicts are informational.
Contributions are welcome and appreciated. To keep the project clean and reviewable:
# 1. Fork the repository and clone your fork
git clone <your-fork-url>
cd pixelproof
# 2. Create a focused feature branch
git checkout -b feature/your-feature-name
# 3. Make your changes — keep commits atomic and well-described
git commit -m "feat: add right-click context menu scan trigger"
# 4. Push and open a pull request against main
git push origin feature/your-feature-nameContribution guidelines:
- Open an issue to discuss significant changes before writing code
- Keep pull requests focused — one feature or fix per PR
- Test against both live API mode and Fallback Mode
- Follow the code style of the surrounding files (no linter currently enforced, but be consistent)
- Reference the issue number in your commit message and PR description
Full details are in CONTRIBUTING.md. First-time contributors: look for issues tagged good first issue.
All notable changes are documented here. This project follows Keep a Changelog conventions.
Added
- Browser-native image scanning on any page via Chrome MV3 content script
- 3-API orchestration pipeline: Reality Defender → Google Gemini → Google Fact Check
- Intelligent caching layer backed by
chrome.storage.local - DOM confidence-score overlays rendered directly over scanned images
- Slide-in verdict panel with full Gemini explanation and matched fact-checks
- Graceful Fallback Mode — demo-safe when APIs are down or keys are absent
- Secure local API key management via the Options page
- Bulk scan (all images on active tab) triggered from the popup
DEMO_CHECKLIST.mdfor structured hackathon presentations- MIT License,
CONTRIBUTING.md, andSECURITY.md
PixelProof would not exist without the following:
| Resource | Role |
|---|---|
| Reality Defender | AI image detection API powering every verdict |
| Google Gemini | Plain-English explanation engine |
| Google Fact Check Tools API | Live fact-check database for claim verification |
| Chrome Extensions Developer Docs | MV3 architecture guidance |
| shields.io | Badge generation for this README |
| Next Byte Hacks V2 — Devpost | Hackathon submission page |
| Everyone who has published a deepfake — unwittingly proving this tool is necessary |
| Name | Harsh Bhanushali |
| harsh@dualmindlab.tech | |
| Alternate | harshu.dev@outlook.com |
| Hackathon | Next Byte Hacks V2 |
| Web | pixelproof.dualmindlab.tech |
Distributed under the MIT License. See LICENSE for full terms.
MIT License — Copyright (c) 2024 Harsh Bhanushali
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction...
🌐 Landing Page · 🎬 Live Demo · 🏆 Devpost
Built for Next Byte Hacks V2 by Harsh Bhanushali — with 🔍 and too much caffeine.
If you're seeing fakes you can't unsee — you're welcome.