Library / SDK
scottyab/rootbeer avatar
scottyab/rootbeer

scottyab/rootbeer: an Android root checker that treats root as an indication, not a verdict

Simple to use root checking Android library and sample app

2,954 stars533 forksJavaApache-2.0

At a glance

What is it?
RootBeer is a Java library and sample app that runs a set of Java and native checks for signs of root on an Android device. It is useful for raising friction, not for building a security boundary, and the README says so itself.
Who is it for?
Adopt scottyab/rootbeer when you need a cheap, offline indication of root and can tolerate false positives and false negatives: a diagnostics screen, a support flow, a game that wants to flag tampering. Do not adopt it as the security boundary for payments, DRM or anything where a bypass is expensive, because the README states plainly that root checking has no guaranteed answer and points to the Play Integrity API for that job.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Activity is slowing. The repository last received commits 6 months ago.
What is it written in?
Mainly Java, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The question RootBeer tries to answer, and who is asking it

The README frames the project around one question: has this device got root? RootBeer answers it by collecting a set of signals and exposing them as a single boolean through isRooted(), plus an isRootedWithBusyBoxCheck() variant. The target user is an Android developer who wants that signal inside an app without writing the detection logic themselves. The library ships with a sample app whose UI exposes the individual checks, which is the honest way to present this kind of tool: you can see which check fired rather than trusting one aggregate result. The README is also unusually direct about the stakes. It states that root equals god, that there is no 100% guaranteed way to check for root, and that results should be treated as an indication alongside other factors. That framing matters more than any individual check, because it tells you where the library belongs in a stack.

What the Java checks actually look for

The check list is a catalogue of artifacts that tend to accompany root rather than a proof of it. checkRootManagementApps looks for installed apps such as SuperSU or Magisk. checkPotentiallyDangerousApps looks for a predefined list of apps that facilitate root access. checkRootCloakingApps tries to spot the tools that hide root from detectors. checkTestKeys inspects whether the firmware is signed with Android test keys, which is the normal state on AOSP builds and some emulators. checkForDangerousProps reads ro.debuggable and ro.secure. checkForBusyBoxBinary looks for the BusyBox binary. checkForSuBinary and checkSuExists look for the su binary, the second via which su. checkForRWSystem checks whether /system is mounted read-write. Every one of these has a limitation the README names, and the limitations are the interesting part. The root management app list goes stale as new tools appear. Test keys only catch devices using test keys. Systemless root does not need a writable /system, so checkForRWSystem misses it. Renamed or hidden su binaries defeat two checks at once.

The native check and why it is not a stronger guarantee

RootBeer calls into a native root checker for an additional su binary check. The README's argument for this is that native checks are typically harder to cloak, and that some root cloaking apps respond by blocking the loading of native libraries that contain certain keywords. That is a real asymmetry: a Java-level check runs in a process the cloaking tool may already control, while a native library load is a different surface. It is not immunity. The native check is the same su binary test, so it inherits the same failure mode: rename or hide the binary and the check returns nothing. Treat the native path as one more signal with a different cost to defeat, not as the check that cannot be fooled.

Installing RootBeer and running a first check

RootBeer is a Gradle dependency. The README shows the API call rather than the dependency coordinates, so the version to use is the one published in the repository's releases, currently 0.1.2. Add the library to your module's build file, then construct a RootBeer instance with a Context and call isRooted(). The README advises calling isRooted() from a background thread because it performs disk I/O, which is a practical constraint: on the main thread you are risking a dropped frame or an ANR. The snippet below is the usage example from the README.

java
RootBeer rootBeer = new RootBeer(context);
if (rootBeer.isRooted()) {
    //we found indication of root
} else {
    //we didn't find indication of root
}

If you want the busybox signal included, the README gives a second entry point. The default isRooted() deliberately excludes busybox because manufacturers sometimes ship that binary in production builds, which produces false positives. The README states that the busybox check was removed from the standard isRooted() path for exactly that reason.

java
rootBeer.isRootedWithBusyBoxCheck();

For a single binary you can call checkForBinary with the BINARY_BUSYBOX constant. The sample app in the repository calls the checks individually, and that is the pattern worth copying while you are evaluating the library: run each check, log which ones fire on your test devices, and only then decide which aggregate call your app should use.

Where RootBeer gives you the wrong answer

False positives have a documented cause. The README says manufacturers sometimes leave the busybox binary in production builds and that this does not always mean the device is rooted, which is why busybox is out of the default path. That leaves a choice: use isRooted() and accept that you will miss rooted devices that only show up through busybox, or use isRootedWithBusyBoxCheck() and accept that some unrooted devices will be flagged. Neither option is wrong, but you have to pick one deliberately. False negatives are structural. The README says RootBeer can be bypassed and links to a write-up on doing so, and it notes that in 2015 the library was defeated when a combination of root cloaking apps was active at the same time, even though it flagged root against each cloaker individually. If your threat model includes a user who is motivated to hide root, this library is the wrong tool on its own. The README's own recommendation for that case is the Google Play Integrity API, which verifies that requests come from an unmodified app binary installed by Google Play on a genuine device.

How this differs from Play Integrity and from shipping no check

The difference from Play Integrity is where the decision is made. RootBeer runs entirely on the device, inside your process, using signals a local attacker can influence. Play Integrity moves the verdict to Google's servers, which is why the README calls it the more robust solution: the app binary, the installer and the device state are assessed remotely. The trade-offs are obvious once stated. RootBeer needs no network, no Google account and no server round trip, and it works on devices and builds where Play services are absent. Play Integrity depends on Google Play, adds a network call and a service dependency, and returns a verdict you have to trust rather than inspect. The third option, shipping no check at all, is underrated for apps where root is not a threat. The README notes that its creators use rooted devices and understand the frustration when apps block them, and it asks users to raise complaints with the app doing the blocking rather than with RootBeer. If your app has no integrity-sensitive feature, a root check mostly creates support tickets.

Maintenance, licence and the cost of upgrading

The repository is not archived and the last push was on 2026-03-17, so there is recent activity. Release history is uneven rather than continuous: 0.1.0 in May 2021, 0.1.1 in September 2024, and 0.1.2 in March 2026. The version numbers tell you the API is treated as pre-1.0, and the check list is the kind of code that ages with the root tooling it targets, so pinning a version and testing before you bump it is reasonable. The licence is Apache-2.0, which is permissive and includes an explicit patent grant; the LICENSE file is at the repository root. Apache-2.0 does not carry the copyleft obligations of the GPL, but it does require you to keep the licence and notice files with any redistribution, and the usual disclaimer of warranty applies. That is a summary of the licence text, not legal advice. If you modify the library and redistribute it, read the LICENSE file and your own counsel rather than this paragraph.

Editorial conclusion

Adopt scottyab/rootbeer when you need a cheap, offline indication of root and can tolerate false positives and false negatives: a diagnostics screen, a support flow, a game that wants to flag tampering. Do not adopt it as the security boundary for payments, DRM or anything where a bypass is expensive, because the README states plainly that root checking has no guaranteed answer and points to the Play Integrity API for that job. Before shipping, verify on your own device fleet which checks fire, since manufacturer busybox builds and systemless root are named in the documentation as sources of wrong answers.

Frequently asked questions

How do I use scottyab/rootbeer in an Android app?

Add the library as a Gradle dependency, then construct a RootBeer object with a Context and call isRooted(). The README advises calling it from a background thread because the checks involve disk I/O.

What is scottyab/rootbeer?

It is a Java library and sample app for Android that runs a set of Java and native checks to give an indication of whether a device has root. The README describes it as a root checker library, not a security guarantee.

Does scottyab/rootbeer detect root reliably?

No. The README states there is no 100% guaranteed way to check for root and that results should be treated as an indication only. It also says RootBeer can be bypassed and links to a write-up showing how.

Why does scottyab/rootbeer not check for busybox by default?

Because manufacturers sometimes leave the busybox binary in production builds, which produces false positives. The README says the busybox check was removed from the standard isRooted() method for that reason, and you can add it back with isRootedWithBusyBoxCheck().

What should I use instead of scottyab/rootbeer for stronger integrity checks?

The README recommends the Google Play Integrity API, which verifies that requests come from your unmodified app binary, installed by Google Play, running on a genuine Android device.

Official sources

  1. Issues
  2. License: Apache-2.0
  3. README
  4. Releases
  5. scottyab/rootbeer on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/scottyab-rootbeer.svg)](https://hysenlabs.com/projects/scottyab-rootbeer)