Detecting Brave
See original GitHub issueHistory / Reference
Brave, historically, has taken steps to prevent websites from detecting whether a user is using Brave. Obviously, a lot of people want to know if a user is using Brave for reasons both good and bad. I’m working under the assumption that Brave doesn’t want a website to be able to detect a user is using Brave.
- https://stackoverflow.com/questions/36523448/how-do-i-tell-if-a-user-is-using-brave-as-their-browser
- https://community.brave.com/t/detecting-a-brave-browser-high-level-stats/68744
- https://community.brave.com/t/make-it-possible-for-website-to-detect-when-you-are-using-brave/40373
- https://community.brave.com/t/browser-detection/23247
- https://www.ctrl.blog/entry/brave-user-agent-detection.html
- https://github.com/brave/browser-laptop/issues/11012
- https://github.com/brave/brave-browser/issues/1052#issuecomment-498795869
For MyCryptoSummer, we wanted to offer users a special treat if they used Brave Browser. Obviously, this required us to detect whether a user was using Brave or not. We were able to successfully detect this with my ghetto-ass Javascript skills. This was a very specific use-case where the consequences of being wrong were low and length of time it needed to work was ~1 month. We also simply wanted to detect true/false for Brave, not as part of larger browser detection / tracking.
How We Did It
- Detect if Chrome:
const ua = window.navigator.userAgent.toLowerCase()
const isChrome = /chrome|crios/.test(ua) && ! /edge|opr\//.test(ua)
- Test for ad blocking
const testForAdBlocker = function(callback) {
const img = new Image;
img.onload = function() {
callback(true);
}
img.onerror = function() {
callback(false);
}
img.src = 'https://mycrypto.com/&showad=TEST_URL_TO_CHECK_FOR_BRAVE_AD_BLOCKING';
}
- Detect if no plugins
navigator.plugins.length > 0
- Detect if two specific plugins
if (plugins[0].name ==="Chrome PDF Plugin" && plugins[1].name==="Chrome PDF Viewer") {
return true
}
Using a combination of the above, we were able to determine, with reasonable certainty, whether a user was using Brave or not. Specifically:
- If user agent is chrome + there are 0 plugins + it blocks ads, then it’s Brave.
- If user agent is chrome + there are exactly two plugins
Chrome PDF Plugin
andChrome PDF Viewer
, then it is Brave (specifically a nightly version of Brave as of August 2019).
Ghetto ass javascript can be found here: https://summer.mycrypto.com/brave.html
Suggested Possible Fixes
Obviously you can band-aid the above and resolve easily, but I think lessons can be learned that apply to ongoing developments / decision-making.
-
Hiding fingerprint is a fingerprint in itself (e.g. having 0 plugins is fucking weird).
-
Doing one special thing (blocking ads) combined with another special thing (having 0 plugins) is even weirder.
-
Most nefarious use-cases / tracking will want a certain level of certainty. Changing things up frequently, or even doing something like randomly serving a different UA each time browser is started or returning random plugins lowers the certainty enough to not be practical.
-
In order for me to figure out the above, I simply asked the question, “what is different about Brave?” and made a list. Then I printed shit out (UA, plugins, etc.) and saw what different browsers returned until I found something striking about Brave. I’m sure there are deeper anomalies that I didn’t think of bc plugins and ad-blocking were so obvious and easy to detect (even with my ghetto JS skills 😉)
Hope this is helpful. I’m not looking for an “answer” or “fix”, just wanted to give you a heads up. 💖
Issue Analytics
- State:
- Created 4 years ago
- Reactions:3
- Comments:5
Top GitHub Comments
So, why not just use navigator.brave? Effectively the code belowif (typeof navigator.brave !== ‘undefined’) saves the troubles of making an additional request and removes dependency on duckduckgo api?..
Connecting to Netflix from Brave 😄