A Manifest V3 browser extension that automatically detects RarJPEG files on web pages and lets you download the hidden RAR archive with one click.
A RarJPEG is a valid JPEG with a RAR archive appended after the JPEG
end-of-image marker (FF D9). The image still renders normally, but the bytes
after FF D9 are a real RAR archive that starts with the Rar! signature.
For every <img> on the page the extension fetches the bytes and checks:
- The file starts with the JPEG SOI signature
FF D8. - A valid archive signature is present after the image. Supported:
- RAR 1.5–4.x:
52 61 72 21 1A 07 00(Rar!\x1A\x07\x00) - RAR 5.0+:
52 61 72 21 1A 07 01 00(Rar!\x1A\x07\x01\x00) - ZIP:
50 4B 03 04(PK\x03\x04) or50 4B 05 06 - 7z:
37 7A BC AF 27 1C
- RAR 1.5–4.x:
- A JPEG EOI marker
FF D9exists before the archive signature. - The appended archive part is at least
minRarSizebytes (sensitivity guard).
The earliest validated archive signature that sits after a JPEG EOI marks the
boundary; everything from there to end-of-file is extracted, with the right
extension (.rar / .zip / .7z).
False-positive protection: matching each archive's full magic (not a short prefix), requiring a real JPEG header and a preceding EOI, and enforcing a configurable minimum archive size.
RarJpegFinder/
├── manifest.json # MV3 manifest
├── icons/ # 16 / 48 / 128 px toolbar icons
├── src/
│ ├── background.js # Service worker: fetch, detect, badge, download
│ ├── content.js # Scans <img>, MutationObserver, on-image badges
│ ├── utils/
│ │ └── detector.js # Pure binary detection (no chrome APIs)
│ ├── popup/ # Toolbar popup: list + toggle + rescan
│ └── options/ # Settings page: enable, sensitivity, limits
├── test/ # RarJPEG fixtures used for verification
└── README.md
- detector.js – pure functions over
Uint8Array. Shared by the content script (listed first incontent_scripts) and the service worker (loaded viaimportScripts). No DOM orchrome.*dependencies, so it is unit-testable in Node. - content.js – collects image URLs, sends them to the background worker,
and draws a small download badge over each detected image. A
MutationObserver(watchingchildList+src/srcset) re-scans images that load dynamically, including lazy-loaded ones. - background.js – fetches images (its
host_permissionslet it read cross-origin bytes without CORS errors, which also covers images that the page itself loaded viafetch/XHRfrom the same URLs), runs detection, caches results per tab, drives the toolbar badge (…while scanning, a red count when done), and performs the download withURL.createObjectURL(revoked once the download completes, with a base64data:fallback). - popup / options – UI for the per-page results list, the global on/off
toggle, and sensitivity settings stored in
chrome.storage.local(works on builds without a Google account, e.g. ungoogled-chromium).
- Enable extension – global on/off switch.
- Show badges on images – toggle the on-image download badges.
- Minimum hidden RAR size – ignore matches whose RAR part is smaller than this (default 32 bytes). Raise it to cut false positives.
- Maximum image size to scan – skip very large downloads (default 25 MB).
- Open
chrome://extensions. - Enable Developer mode.
- Click Load unpacked and select this
RarJpegFinderfolder. - Open any page with images; the toolbar badge shows the count of RarJPEGs found, and a red ⬇ RAR badge appears over each detected image.
The test/ folder contains fixtures (real RAR4/RAR5 RarJPEGs plus negative and
false-positive cases). The detector is verified in Node:
node -e '
const det=require("./src/utils/detector.js"),fs=require("fs");
const b=new Uint8Array(fs.readFileSync("test/rarjpeg5.jpg"));
console.log(det.detect(b,{minRarSize:32}));'To make your own RarJPEG for manual testing:
cat photo.jpg archive.rar > rarjpeg.jpg # Linux/macOS
copy /b photo.jpg + archive.rar rarjpeg.jpg :: WindowsAll detection happens locally inside the extension. No image or file is ever sent to an external server.