尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证Ad-free YouTube and a cleaner web in Safari. On the Mac App Store now; iPhone and iPad are still in review. YouTube ad removal with background playback, plus content blockers from EasyList, EasyPrivacy and RU AdList.
翻译准备中
正在加载完整 README。
查看完整 README ↗Rinse 1.0 is on the Mac App Store for macOS 15 and later. iPhone and iPad are still in review; the same purchase will cover them.
Rinse is a Safari extension app in the spirit of Vinegar, with a site-wide ad blocker built in.
youtube.com. Nothing is collected or sent anywhere.| Extension | What it does | Access |
|---|---|---|
| Rinse for YouTube | Strips ad payloads from the player, skips stitched ads, optional background playback | youtube.com only |
| Rinse Ads | Blocks ad networks (EasyList + RU AdList network rules, 75.7k) | none |
| Rinse Privacy | Blocks trackers and analytics (EasyPrivacy, 56.3k) | none |
| Rinse Page Cleaner | Hides leftover ad slots, banners and brandings (element hiding, 11k) | none |
The app shows at a glance whether everything is on, walks you through enabling the extensions step by step, and holds the settings: background playback and the sites where Rinse is off. It's in English and Russian.
flowchart LR
subgraph YouTube["Rinse for YouTube (Web Extension)"]
BG["background.js<br/>scripting.executeScript<br/>world: MAIN"] --> PAGE["page.js<br/>YouTube's JS world"]
CS["content.js<br/>isolated world"]
end
PAGE -- "prunes adPlacements / adSlots / playerAds<br/>from ytInitialPlayerResponse, fetch, XHR" --> P[YouTube player]
PAGE -- "hides visibility & focus changes" --> P
CS -- "ad-showing? mute · 16× · press Skip" --> P
CS -- "iOS paused on background? play()" --> P
subgraph Blockers["Content Blockers"]
L["EasyList · EasyPrivacy · RU AdList · filters/rinse.txt"] --> C["tools/filters/compile.py"] --> J["blockerList.json ×3"]
end
J --> S[Safari applies rules natively]
YouTube. A custom <video> player like the original Vinegar is no longer possible: as of 2026 YouTube serves no HLS, and direct stream URLs return 403 after about 12–16 MB without a PO token (spike report). So Rinse keeps YouTube's own player and takes the ads out of it:
page.js runs in YouTube's own JS world and deletes the ad fields from player responses before the player reads them. It's injected through scripting.executeScript, because YouTube's CSP blocks a plain <script src>.content.js hides it with rinse.css and mutes it. A separate ad video jumps straight to its end; a stitched one plays at 16×. Then the ad's own Skip button gets pressed, found by its label inside the ad UI.
After a removed or skipped ad, YouTube holds the video back server-side for about the ad's length. That can't be avoided from the page, so a small "Ad skipped · your video starts in a moment" note is shown instead of a frozen-looking player.
YouTube's "Ad blockers are not allowed" popup pauses the video and dims the page. page.js prunes it from the player response; if it still opens, rinse.css hides it and content.js resumes the video. The dimming backdrop is removed by content.js whenever no dialog is displayed over it: a dialog hidden with display: none never finishes its close transition, so YouTube would leave the backdrop over the page, blocking every click.content.js caches it in storage.local and sets <html data-rinse-background> for page.js. When it's on, content.js swallows visibilitychange, pagehide, blur and freeze before YouTube sees them, page.js reports the page as visible, and if iOS still pauses the video while going to the background, it's resumed.Everything else. tools/filters/compile.py converts Adblock Plus syntax into Safari's content-blocker JSON:
@@ exceptions;#@# exceptions;site.* TLD wildcards, turned into page URL filters.What Safari can't express (regex rules, $redirect, scriptlets, procedural selectors) is dropped and counted. The output is verified with WebKit's own compiler, and each CSS selector is checked by WebKit, because a single invalid one would silently disable the 250 selectors batched with it.
nikolaikushner.github.io/rinse · Privacy Policy · Support (also in Russian). The pages live in site/ and are published by .github/workflows/pages.yml on every push to main that changes them.
Requirements: Xcode 27+, XcodeGen (brew install xcodegen), and an Apple Developer team. The team ID is set in project.yml.
scripts/run.sh mac # build and open the Mac app
scripts/run.sh ios # build and install on a connected, unlocked iPhone or iPad
Or run xcodegen generate && open Rinse.xcodeproj and use the Rinse_iOS / Rinse_macOS schemes. Rinse.xcodeproj is generated and not committed.
scripts/release.sh # archive iOS + macOS, sign for App Store Connect, upload
scripts/release.sh ios # or one platform
Bump CURRENT_PROJECT_VERSION in project.yml before each upload: a build number can be used only once.
Signing is automatic with the team in project.yml and the Apple ID signed in to Xcode.
Open the Rinse app once after installing or updating, so Safari reloads the rules.
tools/youtube/try-youtube.swift plays a real YouTube video in a WKWebView with Rinse's scripts and prints a per-second timeline: is an ad showing, is it hidden, does the video advance. tools/youtube/check.sh runs it several times on videos known to show ads; --fake-popup N opens a stand-in for the ad blocker popup at second N, to check that Rinse hides it and resumes the video (--orphan: the dialog is already hidden and goes away, the backdrop stays; --plain: an ordinary dialog, which must stay). Run it before a release; with full Rinse you want ad=0s, and any stall should be covered by the note (silentStall ≤ 1s).
swift tools/youtube/try-youtube.swift oufxWa84Fxk # full Rinse
swift tools/youtube/try-youtube.swift oufxWa84Fxk --no-rinse # baseline
tools/youtube/check.sh 3
scripts/update-filters.sh # download + compile
python3 -m unittest discover -s tools/filters # compiler tests
tools/tests/run-allowlist-tests.sh # allowlist, incl. WebKit
swift tools/filters/validate.swift Extensions/Blockers/*/blockerList.json # WebKit accepts the rules
If WebKit starts rejecting selectors, regenerate the reject list:
python3 tools/filters/compile.py --dump-selectors /tmp/s.txt
swift tools/filters/check-selectors.swift /tmp/s.txt > filters/invalid-selectors.txt
To see Rinse's state on a YouTube page, run localStorage.setItem("rinse-debug", "1") in the page console and reload. A status badge then shows whether page.js ran and how many ad fields were pruned, ads skipped and background resumes.
| Path | What |
|---|---|
App/ | SwiftUI container app: extension status, rule reload, how to enable |
Shared/ | Code shared by the app targets |
Extensions/YouTube/ | Safari Web Extension: content.js, page.js, background.js |
Extensions/Blockers/{Ads,Privacy,Cosmetic}/ | Content blockers; blockerList.json is generated, don't edit it by hand |
filters/ | sources.json (which lists go into which blocker), rinse.txt (our own rules), invalid-selectors.txt |
tools/filters/ | Filter compiler, its tests, and WebKit-based validators |
scripts/ | run.sh, update-filters.sh, icon generator |
site/ | Website for GitHub Pages: landing, privacy policy, support (EN + RU) |
Config/PrivacyInfo.xcprivacy | Privacy manifest bundled in the app and every extension |
docs/appstore/ | App Store listing (EN + RU), review notes, screenshots and their gallery (gallery.html); built by tools/appstore/make-screenshots.sh and gallery.py |
plans/, docs/spikes/ | Implementation plan and research notes |
spikes/ | Throwaway experiments and their tests, kept for reference |
Rinse 1.0 is on the Mac App Store. It has been tested on an iPhone 14 Plus and a Mac, and not yet on iPad. iPhone and iPad are not in the store yet.
page.js and content.js fall back to YouTube's normal player rather than a black screen.See plans/rinse.md for the roadmap: an element picker ("hide this"), a per-site allowlist, Shorts, embedded players, and the iPhone and iPad release.
Copyright © 2026 Mikalai Kushner.
blockerList.json files stay under those licenses. See LICENSES.md.Inspired by Vinegar by And a Dinosaur. Rinse is not affiliated with YouTube or Google.
Rinse 1.0 уже в Mac App Store для macOS 15 и новее. iPhone и iPad ещё на проверке.
Rinse — набор расширений Safari для iPhone, iPad и Mac.
youtube.com.Сборка: scripts/run.sh mac или scripts/run.sh ios. Затем включите все четыре расширения в настройках Safari и один раз откройте приложение Rinse.
Лицензия. Та же покупка покроет iPhone и iPad, когда их версии одобрят. Продавать Rinse и выкладывать его в магазин приложений может только автор. Себе собрать для личного пользования можно. Название «Rinse» и иконка в эту лицензию не входят. Списки EasyList, EasyPrivacy и RU AdList чужие, и их лицензии по-прежнему разрешают другим ими пользоваться.