Sulkta fork of NewPipe — KMP/Compose Android YouTube client with built-in SponsorBlock + Return YouTube Dislike. Day-1 build, GPL-3.0-or-later per upstream.
Find a file
Kayos cbdba302ce vc=38: round-3 audit-fix sprint — 9 HIGH + 7 MED
Three round-3 Opus audits ran on vc=37. NO new CRITs (round-2 work
held) but real new HIGHs — several were vc=37 own-goals.

HIGH
  R3-1  recordAllWatches dropped import on capacity=0. Old: when
        watches store hit MAX_WATCHES (50), capacity=0, the whole
        import was discarded silently. New: build fresh import list
        capped at MAX_WATCHES, then combine + take(MAX_WATCHES) so
        imports always land (truncating oldest current entries).
        Also: skip SP write when next === before (no-op import on
        already-saturated store no longer thrashes disk).
        New recordAllSearches with same shape — round-3 CVE MED-6:
        importHistory was per-row recordSearch.
  R3-2  / CVE-2  SubscriptionsStore.addAll counter race. The vc=36
        size-delta fix snapshot `cur = _subs.value` BEFORE
        updateAndGet, so a concurrent toggle inflated `added`. New:
        AtomicInteger reset at the start of each lambda re-run,
        counted by checking each ref against the pre-image inside
        the CAS. Exactly the additions THIS call made.
  R3-3  refresh() empty-channels didn't cancel inFlight. Cancel
        moved to the top of refresh() unconditionally so a refresh
        on the prior sub set is killed before the empty branch
        clears + wipes disk.
        clearInMemoryCache also cancels inFlight — without it, a
        cache-disable flip during a refresh could see fetchChannelInto
        re-populate the just-cleared map.
  R3-4  Non-atomic `_ui.value = it.copy(...)` at init hydrate path
        and clearInMemoryCache. Replaced with `_ui.update {}` for
        atomicity vs concurrent refresh writes. init's
        lastFetchedAt write now uses maxOf so it never regresses
        past a fresh refresh value.
  CVE-1 state.error rendered raw UniFFI/Rust error strings to UI
        — NetworkError::Recaptcha { url } embeds full signed
        googlevideo URL. User screenshots a "reCAPTCHA at <URL>"
        banner → leak. All four VMs (Channel/Detail/Feed/Search)
        now scrub via LogDump.scrubLine before storing.
  CVE-3 pruneCacheToSubs in init can clobber concurrent
        fetchChannelInto writes. init's putAll → putIfAbsent so
        a fresh entry from a parallel refresh isn't overwritten
        with disk-stale data.
  CVE-4 SIGNED_PARAM_RE over-redacted short tokens (`\bn=`
        matched `n=42` counters from any wrapped lib). Split into
        SIGNED_PARAM_LONG_RE (signature/sparams/lsig/cpn/expire/
        pot/sig/key — match anywhere) and SIGNED_PARAM_SHORT_RE
        (n/mn/ms/mo/pl/ip/ei — require `[?&]` immediately before).
  Func-HIGH-1 refresh() swallowed CancellationException as a
        user-visible error. Spam-tapping Refresh produced a
        "refresh failed: StandaloneCoroutineCancelled" banner.
        Re-throw CancellationException; catch only real errors.

MED
  R3-5  reactiveFilter did N `.lowercase()` allocations per
        keystroke. Switched to contains(ignoreCase = true) — zero
        allocations.
  CVE-MED-5  FileProvider cache-path was "." (whole cacheDir,
        including SettingsImport workdirs). Narrowed to "logs/";
        LogDump.capture now writes to cacheDir/logs/ to match.
  CVE-MED-7  Downloader.Request.setTitle was the raw title
        (bidi-override / control chars possible). Switched to
        safeTitle.
  CVE-MED-8 Rust hello_from_rust value-log scrubbed to name_len.
  Func-LOW-4 recordAllWatches skip-write-on-no-change (`next !==
        before`).

Deferred to a follow-up (not user-facing this ship):
  R3-MED-6 — Settings setMaxResolution/setThemeMode/setCacheEnabled
        not atomic via updateAndGet. Inconsistent with toggle()
        but the Switch UI throttles enough that no real race.
  R3-MED-8 — Minibar play-button reads live controller.isPlaying
        instead of listener-tracked. One-frame oscillation on
        super-fast double-tap.
  R3-LOW — collectAsState vs collectAsStateWithLifecycle drift.
  Func-LOW-6 — refreshIfStale isActive check is TOCTOU on a
        non-existent multi-threaded call surface (LaunchedEffect
        + button are both Main).
2026-05-25 14:29:32 -07:00
.github Update dependencies to latest stable releases 2026-04-26 12:14:57 +08:00
.idea add NP icon for Android Studio's NewUI 2024-07-02 09:31:34 +02:00
app Translated using Weblate (Dutch) 2026-05-23 20:15:02 +00:00
assets Improve image placeholders 2022-07-14 14:14:32 +02:00
buildSrc vc=38: round-3 audit-fix sprint — 9 HIGH + 7 MED 2026-05-25 14:29:32 -07:00
checkstyle Make checkstyle accept javadocs with long links 2024-03-30 15:49:06 +01:00
desktopApp Better share version information between modules 2026-05-20 18:27:08 +08:00
doc Fix new badge links on Readme being rendered incorrectly 2025-07-19 22:45:32 +05:30
docs/sulkta Sulkta day-2: search → detail → player → SponsorBlock + RYD 2026-05-23 19:22:52 -07:00
fastlane/metadata/android Translated using Weblate (Dutch) 2026-05-23 20:15:02 +00:00
gradle Merge branch 'master' into dev 2026-05-23 20:18:19 +02:00
iosApp Initial support for compose multiplatform 2026-05-19 12:22:31 +08:00
rust vc=38: round-3 audit-fix sprint — 9 HIGH + 7 MED 2026-05-25 14:29:32 -07:00
shared shared: Add missing settings implementation 2026-05-23 16:14:52 +08:00
strawApp vc=38: round-3 audit-fix sprint — 9 HIGH + 7 MED 2026-05-25 14:29:32 -07:00
.editorconfig ktlint: Drop non-required backing-property-naming supression 2026-01-24 00:32:03 +08:00
.gitignore v0.1.0-U (vc=8): Phase U-1 + U-2 — Rust core + rustypipe search 2026-05-24 08:36:50 -07:00
build.gradle.kts Initial support for compose multiplatform 2026-05-19 12:22:31 +08:00
gradle.properties Upgrade AGP to 9.2.0 2026-05-16 12:25:24 +08:00
gradlew Update Gradle and wrapper to 9.5.1 2026-05-16 12:34:57 +08:00
gradlew.bat Update Gradle and wrapper to 9.5.1 2026-05-16 12:34:57 +08:00
LICENSE Update license to latest version of https://www.gnu.org/licenses/gpl-3.0.txt 2022-03-19 17:39:06 +01:00
README.md Fix new badge links on Readme being rendered incorrectly 2025-07-19 22:45:32 +05:30
settings.gradle.kts Sulkta day-1: straw — KMP/Compose YouTube client fork 2026-05-23 17:37:55 -07:00

We are rewriting large chunks of the codebase, to bring about a modern and stable NewPipe! You can download nightly builds here.

Please work on the refactor branch if you want to contribute new features. The current codebase is in maintenance mode and will only receive bugfixes.

NewPipe

A libre lightweight streaming front-end for Android.

Get it on F-Droid


ScreenshotsSupported ServicesDescriptionFeaturesInstallation and updatesContributionDonateLicense

WebsiteBlogFAQPress


Read this document in other languages: Deutsch, English, Español, Français, हिन्दी, Italiano, 한국어, Português Brasil, Polski, ਪੰਜਾਬੀ , 日本語, Română, Soomaali, Türkçe, 正體中文, অসমীয়া, Српски, العربية

Warning

THIS APP IS IN BETA, SO YOU MAY ENCOUNTER BUGS. IF YOU DO, OPEN AN ISSUE IN OUR GITHUB REPOSITORY BY FILLING OUT THE ISSUE TEMPLATE.

PUTTING NEWPIPE, OR ANY FORK OF IT, INTO THE GOOGLE PLAY STORE VIOLATES THEIR TERMS AND CONDITIONS.

Screenshots



Supported Services

NewPipe currently supports these services:

As you can see, NewPipe supports multiple video and audio services. Though it started off with YouTube, other people have added more services over the years, making NewPipe more and more versatile!

Partially due to circumstance, and partially due to its popularity, YouTube is the best supported out of these services. If you use or are familiar with any of these other services, please help us improve support for them! We're looking for maintainers for SoundCloud and PeerTube.

If you intend to add a new service, please get in touch with us first! Our docs provide more information on how a new service can be added to the app and to the NewPipe Extractor.

Description

NewPipe works by fetching the required data from the official API (e.g. PeerTube) of the service you're using. If the official API is restricted (e.g. YouTube) for our purposes, or is proprietary, the app parses the website or uses an internal API instead. This means that you don't need an account on any service to use NewPipe.

Also, since they are free and open source software, neither the app nor the Extractor use any proprietary libraries or frameworks, such as Google Play Services. This means you can use NewPipe on devices or custom ROMs that do not have Google apps installed.

Features

  • Watch videos at resolutions up to 4K
  • Listen to audio in the background, only loading the audio stream to save data
  • Popup mode (floating player, aka Picture-in-Picture)
  • Watch live streams
  • Show/hide subtitles/closed captions
  • Search videos and audios (on YouTube, you can specify the content language as well)
  • Enqueue videos (and optionally save them as local playlists)
  • Show/hide general information about videos (such as description and tags)
  • Show/hide next/related videos
  • Show/hide comments
  • Search videos, audios, channels, playlists and albums
  • Browse videos and audios within a channel
  • Subscribe to channels (yes, without logging into any account!)
  • Get notifications about new videos from channels you're subscribed to
  • Create and edit channel groups (for easier browsing and management)
  • Browse video feeds generated from your channel groups
  • View and search your watch history
  • Search and watch playlists (these are remote playlists, which means they're fetched from the service you're browsing)
  • Create and edit local playlists (these are created and saved within the app, and have nothing to do with any service)
  • Download videos/audios/subtitles (closed captions)
  • Open in Kodi
  • Watch/Block age-restricted material

Installation and updates

You can install NewPipe using one of the following methods:

  1. Add our custom repo to F-Droid and install it from there. The instructions are here: https://newpipe.net/FAQ/tutorials/install-add-fdroid-repo/
  2. Download the APK from GitHub Releases, compare the signing key and install it.
  3. Update via F-Droid. This is the slowest method of getting updates, as F-Droid must recognize changes, build the APK itself, sign it, and then push the update to users.
  4. Build a debug APK yourself. This is the fastest way to get new features on your device, but is much more complicated, so we recommend using one of the other methods.
  5. If you're interested in a specific feature or bugfix provided in a Pull Request in this repo, you can also download its APK from within the PR. Read the PR description for instructions. The great thing about PR-specific APKs is that they're installed side-by-side the official app, so you don't have to worry about losing your data or messing anything up.

We recommend method 1 for most users. APKs installed using method 1 or 2 are compatible with each other (meaning that if you installed NewPipe using either method 1 or 2, you can also update NewPipe using the other), but not with those installed using method 3. This is due to the same signing key (ours) being used for 1 and 2, but a different signing key (F-Droid's) being used for 3. Building a debug APK using method 4 excludes a key entirely. Signing keys help ensure that a user isn't tricked into installing a malicious update to an app. When using method 5, each APK is signed with a different random key supplied by GitHub Actions, so you cannot even update it. You will have to backup and restore the app data each time you wish to use a new APK.

In the meanwhile, if you want to switch sources for some reason (e.g. NewPipe's core functionality breaks and F-Droid doesn't have the latest update yet), we recommend following this procedure:

  1. Back up your data via Settings > Backup and Restore > Export Database so you keep your history, subscriptions, and playlists
  2. Uninstall NewPipe
  3. Download the APK from the new source and install it
  4. Import the data from step 1 via Settings > Backup and Restore > Import Database

Note

When you're importing a database into the official app, always make sure that it is the one you exported from the official app. If you import a database exported from an APK other than the official app, it may break things. Such an action is unsupported, and you should only do so when you're absolutely certain you know what you're doing.

APK Info

This is the SHA fingerprint of NewPipe's signing key to verify downloaded APKs which are signed by us. The fingerprint is also available on NewPipe's website. This is relevant for method 2.

CB:84:06:9B:D6:81:16:BA:FA:E5:EE:4E:E5:B0:8A:56:7A:A6:D8:98:40:4E:7C:B1:2F:9E:75:6D:F5:CF:5C:AB

Contribution

Whether you have ideas, translations, design changes, code cleaning, or even major code changes, help is always welcome. The app gets better and better with each contribution, no matter how big or small! If you'd like to get involved, check our contribution notes.

Translation status

Donate

If you like NewPipe, you're welcome to send a donation. We prefer Liberapay, as it is both open-source and non-profit. For further info on donating to NewPipe, please visit our website.

Liberapay Visit NewPipe at liberapay.com Donate via Liberapay

Privacy Policy

The NewPipe project aims to provide a private, anonymous experience for using web-based media services. Therefore, the app does not collect any data without your consent. NewPipe's privacy policy explains in detail what data is sent and stored when you send a crash report, or leave a comment in our blog. You can find the document here.

License

GNU GPLv3 Image

NewPipe is Free Software: You can use, study, share, and improve it at will. Specifically you can redistribute and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.