Keep the apps. Lose the part that eats your evening
No AI needed

Every step written out. No terminal experience needed. Pick your setup.

Use Instagram and YouTube without short-form video. Free, open source, no paywall, no ads, no analytics.
NoScroll removes Reels, Shorts, Explore and algorithmically suggested content — and keeps the parts you actually opened the app for: messages, the people you follow, and posting. When a friend sends you a reel you can watch that video. You just can't scroll to the next one.
Eight services: Instagram and YouTube are probe-verified against the live sites; X, TikTok, Facebook, LinkedIn, Snapchat and Reddit ship as beta and are labelled so in the app.
Status: pre-release. The engine, rule bundles, both native shells and the shield layers are written and tested, and both the iPhone and Android apps build and run. Not yet submitted to either store — see What's not done.
Two layers. The second is the one that matters.
1. The wrapper. NoScroll loads the platforms' own mobile websites in an embedded browser and injects a small engine that hides or removes the endless surfaces. Your session cookies stay on your device.
2. The shield. A wrapper on its own enforces nothing — you'd just open Safari. So NoScroll also shields the real Instagram and YouTube apps at the OS level (iOS Screen Time / FamilyControls, Android AccessibilityService), which makes the stripped version the way in rather than a suggestion.
engine/ TypeScript → one IIFE. The entire blocking implementation.
rules/ Signed JSON rule bundles. Data, not code — updatable without an app release.
ios/ Swift. WKWebView shell + FamilyControls + three Screen Time extensions
+ a WidgetKit extension (home-screen shortcuts via noscroll://open/<service>).
android/ Kotlin. WebView shell + AccessibilityService.
probe/ Playwright smoke tests, run every 6h against live Instagram and YouTube.
tools/ Bundle signing, cross-language canonicalisation check, engine sync.
The engine is byte-identical on both platforms. Everything platform-specific stays in the shells.
iOS. First run is a narrative, not a checklist: how much you scroll → how old you are → your life in weeks, with every band and the percentage derived from your two answers (at 18, scrolling 4.8h of a 5h daily surplus, that is 96% of your remaining free time). Then the permissions, then out.
Home is one service at a time, with today's usage, that service's switches, and a five-tab shell —
Sleep, everything-blocked, Home, Shield, You. A WidgetKit extension puts the same services on your
home screen, opening through NoScroll via noscroll://open/<service>.
Android does not have this UI yet. There is no onboarding narrative, no five-tab shell, and no widget. What exists: the wrapper (Instagram and YouTube, with a button to switch between them) and the shield, plus a Status screen showing whether the accessibility permission is granted and which apps are shielded — reachable from a button in the wrapper, not a settings tab. Fresh installs shield Instagram and YouTube by default the same as iOS does. Building Android up to the same onboarding/shell UI iOS has is open work, not a bug — see the install guide, which should say so at the point a user would otherwise expect to see it.
Every competitor in this category hardcodes CSS selectors and patches them reactively, which is why they visibly leak. NoScroll ships selectors as an ed25519-signed JSON bundle fetched at runtime with a three-tier fallback — remote → cached → baked into the binary — so a cold first launch with no network still blocks, and an upstream redesign is fixed in minutes instead of an App Store review cycle.
Every rule declares expectMin. The engine counts what it actually matched and reports anomalies,
so a rotted selector raises an alert before a user notices.
Rules are open to pull requests. If Instagram changes something and NoScroll starts leaking, you can fix it yourself — see docs/RULES.md.
Every block is a switch you own. The core ones — Reels, Shorts, Explore, suggested posts — arrive switched on, so a fresh install works with no setup, and first-run onboarding shows you every switch once so nothing is a surprise later. But you can turn any of them off, at any time, in Settings.
The product has an opinion. It doesn't take the choice away.
The engine MUST NOT hide, remove, restyle, or observe any node on an auth surface.
Hard-coded in engine/src/authguard.ts, not overridable by any rule
bundle, and enforced by a CI test that fails the build.
Two reasons. A hiding rule that swallows Instagram's own security interstitial bricks login with no visible error. And Apple 5.1.1(vi) treats credential harvesting as developer-program removal — refusing to look at a login page at all is what keeps NoScroll provably clear of it.
Verified against the real login page by the live probe, not just in a test DOM.
Two tiers, stated precisely, because vagueness here is what makes people call a wrapper a phishing app:
{ruleId, expected, actual, bundleVersion} — never a URL, never page content. See
engine/src/bridge.ts.No analytics SDK. No ad pixel. No crash reporter carrying identifiers. No tracking on the website or the legal pages.
Full detail: docs/PRIVACY.md.
Honestly, because a feature list that overpromises is the thing this project is reacting to:
com.apple.developer.family-controls entitlement is
gated by Apple, takes days-to-weeks, and can be denied — see docs/ENTITLEMENT.md.
It has to be granted before the shield layer can run on a device.NOSCROLL_ENTITLEMENTS) because wiring it unconditionally breaks signing for any account
without Apple's approval. Without it, "Grant access" explains why rather than failing with
Apple's Couldn't communicate with a helper application.PROBE_IG_STATE. Use a dedicated probe
account, never a personal one.AGPL-3.0-or-later. See LICENCE.
Rule bundles seeded from MIT-licensed filter lists — gijsdev/ublock-hide-yt-shorts and
BevizLaszlo/UBlock-Filters-for-Social-Media — with provenance recorded per rule.
NoScroll is not affiliated with, endorsed by, or connected to Meta, Instagram, Google or YouTube.