@fingerprintjs/botd
Version:
botd is a browser library for JavaScript bot detection
897 lines (847 loc) • 32.5 kB
JavaScript
/**
* Fingerprint BotD v1.9.1 - Copyright (c) FingerprintJS, Inc, 2024 (https://fingerprint.com)
* Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.
*/
import { __extends, __awaiter, __generator, __spreadArray } from 'tslib';
var version = "1.9.1";
/**
* Enum for types of bots.
* Specific types of bots come first, followed by automation technologies.
*
* @readonly
* @enum {string}
*/
var BotKind = {
// Object is used instead of Typescript enum to avoid emitting IIFE which might be affected by further tree-shaking.
// See example of compiled enums https://stackoverflow.com/q/47363996)
Awesomium: 'awesomium',
Cef: 'cef',
CefSharp: 'cefsharp',
CoachJS: 'coachjs',
Electron: 'electron',
FMiner: 'fminer',
Geb: 'geb',
NightmareJS: 'nightmarejs',
Phantomas: 'phantomas',
PhantomJS: 'phantomjs',
Rhino: 'rhino',
Selenium: 'selenium',
Sequentum: 'sequentum',
SlimerJS: 'slimerjs',
WebDriverIO: 'webdriverio',
WebDriver: 'webdriver',
HeadlessChrome: 'headless_chrome',
Unknown: 'unknown',
};
/**
* Bot detection error.
*/
var BotdError = /** @class */ (function (_super) {
__extends(BotdError, _super);
/**
* Creates a new BotdError.
*
* @class
*/
function BotdError(state, message) {
var _this = _super.call(this, message) || this;
_this.state = state;
_this.name = 'BotdError';
Object.setPrototypeOf(_this, BotdError.prototype);
return _this;
}
return BotdError;
}(Error));
function detect(components, detectors) {
var detections = {};
var finalDetection = {
bot: false,
};
for (var detectorName in detectors) {
var detector = detectors[detectorName];
var detectorRes = detector(components);
var detection = { bot: false };
if (typeof detectorRes === 'string') {
detection = { bot: true, botKind: detectorRes };
}
else if (detectorRes) {
detection = { bot: true, botKind: BotKind.Unknown };
}
detections[detectorName] = detection;
if (detection.bot) {
finalDetection = detection;
}
}
return [detections, finalDetection];
}
function collect(sources) {
return __awaiter(this, void 0, void 0, function () {
var components, sourcesKeys;
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
components = {};
sourcesKeys = Object.keys(sources);
return [4 /*yield*/, Promise.all(sourcesKeys.map(function (sourceKey) { return __awaiter(_this, void 0, void 0, function () {
var res, _a, _b, error_1;
var _c;
return __generator(this, function (_d) {
switch (_d.label) {
case 0:
res = sources[sourceKey];
_d.label = 1;
case 1:
_d.trys.push([1, 3, , 4]);
_a = components;
_b = sourceKey;
_c = {};
return [4 /*yield*/, res()];
case 2:
_a[_b] = (_c.value = _d.sent(),
_c.state = 0 /* State.Success */,
_c);
return [3 /*break*/, 4];
case 3:
error_1 = _d.sent();
if (error_1 instanceof BotdError) {
components[sourceKey] = {
state: error_1.state,
error: "".concat(error_1.name, ": ").concat(error_1.message),
};
}
else {
components[sourceKey] = {
state: -3 /* State.UnexpectedBehaviour */,
error: error_1 instanceof Error ? "".concat(error_1.name, ": ").concat(error_1.message) : String(error_1),
};
}
return [3 /*break*/, 4];
case 4: return [2 /*return*/];
}
});
}); }))];
case 1:
_a.sent();
return [2 /*return*/, components];
}
});
});
}
function detectAppVersion(_a) {
var appVersion = _a.appVersion;
if (appVersion.state !== 0 /* State.Success */)
return false;
if (/headless/i.test(appVersion.value))
return BotKind.HeadlessChrome;
if (/electron/i.test(appVersion.value))
return BotKind.Electron;
if (/slimerjs/i.test(appVersion.value))
return BotKind.SlimerJS;
}
function arrayIncludes(arr, value) {
return arr.indexOf(value) !== -1;
}
function strIncludes(str, value) {
return str.indexOf(value) !== -1;
}
function arrayFind(array, callback) {
if ('find' in array)
return array.find(callback);
for (var i = 0; i < array.length; i++) {
if (callback(array[i], i, array))
return array[i];
}
return undefined;
}
function getObjectProps(obj) {
return Object.getOwnPropertyNames(obj);
}
function includes(arr) {
var keys = [];
for (var _i = 1; _i < arguments.length; _i++) {
keys[_i - 1] = arguments[_i];
}
var _loop_1 = function (key) {
if (typeof key === 'string') {
if (arrayIncludes(arr, key))
return { value: true };
}
else {
var match = arrayFind(arr, function (value) { return key.test(value); });
if (match != null)
return { value: true };
}
};
for (var _a = 0, keys_1 = keys; _a < keys_1.length; _a++) {
var key = keys_1[_a];
var state_1 = _loop_1(key);
if (typeof state_1 === "object")
return state_1.value;
}
return false;
}
function countTruthy(values) {
return values.reduce(function (sum, value) { return sum + (value ? 1 : 0); }, 0);
}
function detectDocumentAttributes(_a) {
var documentElementKeys = _a.documentElementKeys;
if (documentElementKeys.state !== 0 /* State.Success */)
return false;
if (includes(documentElementKeys.value, 'selenium', 'webdriver', 'driver')) {
return BotKind.Selenium;
}
}
function detectErrorTrace(_a) {
var errorTrace = _a.errorTrace;
if (errorTrace.state !== 0 /* State.Success */)
return false;
if (/PhantomJS/i.test(errorTrace.value))
return BotKind.PhantomJS;
}
function detectEvalLengthInconsistency(_a) {
var evalLength = _a.evalLength, browserKind = _a.browserKind, browserEngineKind = _a.browserEngineKind;
if (evalLength.state !== 0 /* State.Success */ ||
browserKind.state !== 0 /* State.Success */ ||
browserEngineKind.state !== 0 /* State.Success */)
return;
var length = evalLength.value;
if (browserEngineKind.value === "unknown" /* BrowserEngineKind.Unknown */)
return false;
return ((length === 37 && !arrayIncludes(["webkit" /* BrowserEngineKind.Webkit */, "gecko" /* BrowserEngineKind.Gecko */], browserEngineKind.value)) ||
(length === 39 && !arrayIncludes(["internet_explorer" /* BrowserKind.IE */], browserKind.value)) ||
(length === 33 && !arrayIncludes(["chromium" /* BrowserEngineKind.Chromium */], browserEngineKind.value)));
}
function detectFunctionBind(_a) {
var functionBind = _a.functionBind;
if (functionBind.state === -2 /* State.NotFunction */)
return BotKind.PhantomJS;
}
function detectLanguagesLengthInconsistency(_a) {
var languages = _a.languages;
if (languages.state === 0 /* State.Success */ && languages.value.length === 0) {
return BotKind.HeadlessChrome;
}
}
function detectMimeTypesConsistent(_a) {
var mimeTypesConsistent = _a.mimeTypesConsistent;
if (mimeTypesConsistent.state === 0 /* State.Success */ && !mimeTypesConsistent.value) {
return BotKind.Unknown;
}
}
function detectNotificationPermissions(_a) {
var notificationPermissions = _a.notificationPermissions, browserKind = _a.browserKind;
if (browserKind.state !== 0 /* State.Success */ || browserKind.value !== "chrome" /* BrowserKind.Chrome */)
return false;
if (notificationPermissions.state === 0 /* State.Success */ && notificationPermissions.value) {
return BotKind.HeadlessChrome;
}
}
function detectPluginsArray(_a) {
var pluginsArray = _a.pluginsArray;
if (pluginsArray.state === 0 /* State.Success */ && !pluginsArray.value)
return BotKind.HeadlessChrome;
}
function detectPluginsLengthInconsistency(_a) {
var pluginsLength = _a.pluginsLength, android = _a.android, browserKind = _a.browserKind, browserEngineKind = _a.browserEngineKind;
if (pluginsLength.state !== 0 /* State.Success */ ||
android.state !== 0 /* State.Success */ ||
browserKind.state !== 0 /* State.Success */ ||
browserEngineKind.state !== 0 /* State.Success */)
return;
if (browserKind.value !== "chrome" /* BrowserKind.Chrome */ ||
android.value ||
browserEngineKind.value !== "chromium" /* BrowserEngineKind.Chromium */)
return;
if (pluginsLength.value === 0)
return BotKind.HeadlessChrome;
}
function detectProcess(_a) {
var _b;
var process = _a.process;
if (process.state !== 0 /* State.Success */)
return false;
if (process.value.type === 'renderer' || ((_b = process.value.versions) === null || _b === void 0 ? void 0 : _b.electron) != null)
return BotKind.Electron;
}
function detectProductSub(_a) {
var productSub = _a.productSub, browserKind = _a.browserKind;
if (productSub.state !== 0 /* State.Success */ || browserKind.state !== 0 /* State.Success */)
return false;
if ((browserKind.value === "chrome" /* BrowserKind.Chrome */ ||
browserKind.value === "safari" /* BrowserKind.Safari */ ||
browserKind.value === "opera" /* BrowserKind.Opera */ ||
browserKind.value === "wechat" /* BrowserKind.WeChat */) &&
productSub.value !== '20030107')
return BotKind.Unknown;
}
function detectUserAgent(_a) {
var userAgent = _a.userAgent;
if (userAgent.state !== 0 /* State.Success */)
return false;
if (/PhantomJS/i.test(userAgent.value))
return BotKind.PhantomJS;
if (/Headless/i.test(userAgent.value))
return BotKind.HeadlessChrome;
if (/Electron/i.test(userAgent.value))
return BotKind.Electron;
if (/slimerjs/i.test(userAgent.value))
return BotKind.SlimerJS;
}
function detectWebDriver(_a) {
var webDriver = _a.webDriver;
if (webDriver.state === 0 /* State.Success */ && webDriver.value)
return BotKind.HeadlessChrome;
}
function detectWebGL(_a) {
var webGL = _a.webGL;
if (webGL.state === 0 /* State.Success */) {
var _b = webGL.value, vendor = _b.vendor, renderer = _b.renderer;
if (vendor == 'Brian Paul' && renderer == 'Mesa OffScreen') {
return BotKind.HeadlessChrome;
}
}
}
function detectWindowExternal(_a) {
var windowExternal = _a.windowExternal;
if (windowExternal.state !== 0 /* State.Success */)
return false;
if (/Sequentum/i.test(windowExternal.value))
return BotKind.Sequentum;
}
function detectWindowSize(_a) {
var windowSize = _a.windowSize, documentFocus = _a.documentFocus;
if (windowSize.state !== 0 /* State.Success */ || documentFocus.state !== 0 /* State.Success */)
return false;
var _b = windowSize.value, outerWidth = _b.outerWidth, outerHeight = _b.outerHeight;
// When a page is opened in a new tab without focusing it right away, the window outer size is 0x0
if (!documentFocus.value)
return;
if (outerWidth === 0 && outerHeight === 0)
return BotKind.HeadlessChrome;
}
function detectDistinctiveProperties(_a) {
var distinctiveProps = _a.distinctiveProps;
if (distinctiveProps.state !== 0 /* State.Success */)
return false;
var value = distinctiveProps.value;
var bot;
for (bot in value)
if (value[bot])
return bot;
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
var detectors = {
detectAppVersion: detectAppVersion,
detectDocumentAttributes: detectDocumentAttributes,
detectErrorTrace: detectErrorTrace,
detectEvalLengthInconsistency: detectEvalLengthInconsistency,
detectFunctionBind: detectFunctionBind,
detectLanguagesLengthInconsistency: detectLanguagesLengthInconsistency,
detectNotificationPermissions: detectNotificationPermissions,
detectPluginsArray: detectPluginsArray,
detectPluginsLengthInconsistency: detectPluginsLengthInconsistency,
detectProcess: detectProcess,
detectUserAgent: detectUserAgent,
detectWebDriver: detectWebDriver,
detectWebGL: detectWebGL,
detectWindowExternal: detectWindowExternal,
detectWindowSize: detectWindowSize,
detectMimeTypesConsistent: detectMimeTypesConsistent,
detectProductSub: detectProductSub,
detectDistinctiveProperties: detectDistinctiveProperties,
};
function getAppVersion() {
var appVersion = navigator.appVersion;
if (appVersion == undefined) {
throw new BotdError(-1 /* State.Undefined */, 'navigator.appVersion is undefined');
}
return appVersion;
}
function getDocumentElementKeys() {
if (document.documentElement === undefined) {
throw new BotdError(-1 /* State.Undefined */, 'document.documentElement is undefined');
}
var documentElement = document.documentElement;
if (typeof documentElement.getAttributeNames !== 'function') {
throw new BotdError(-2 /* State.NotFunction */, 'document.documentElement.getAttributeNames is not a function');
}
return documentElement.getAttributeNames();
}
function getErrorTrace() {
try {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
null[0]();
}
catch (error) {
if (error instanceof Error && error['stack'] != null) {
return error.stack.toString();
}
}
throw new BotdError(-3 /* State.UnexpectedBehaviour */, 'errorTrace signal unexpected behaviour');
}
function getEvalLength() {
return eval.toString().length;
}
function getFunctionBind() {
if (Function.prototype.bind === undefined) {
throw new BotdError(-2 /* State.NotFunction */, 'Function.prototype.bind is undefined');
}
return Function.prototype.bind.toString();
}
function getBrowserEngineKind() {
var _a, _b;
// Based on research in October 2020. Tested to detect Chromium 42-86.
var w = window;
var n = navigator;
if (countTruthy([
'webkitPersistentStorage' in n,
'webkitTemporaryStorage' in n,
n.vendor.indexOf('Google') === 0,
'webkitResolveLocalFileSystemURL' in w,
'BatteryManager' in w,
'webkitMediaStream' in w,
'webkitSpeechGrammar' in w,
]) >= 5) {
return "chromium" /* BrowserEngineKind.Chromium */;
}
if (countTruthy([
'ApplePayError' in w,
'CSSPrimitiveValue' in w,
'Counter' in w,
n.vendor.indexOf('Apple') === 0,
'getStorageUpdates' in n,
'WebKitMediaKeys' in w,
]) >= 4) {
return "webkit" /* BrowserEngineKind.Webkit */;
}
if (countTruthy([
'buildID' in navigator,
'MozAppearance' in ((_b = (_a = document.documentElement) === null || _a === void 0 ? void 0 : _a.style) !== null && _b !== void 0 ? _b : {}),
'onmozfullscreenchange' in w,
'mozInnerScreenX' in w,
'CSSMozDocumentRule' in w,
'CanvasCaptureMediaStream' in w,
]) >= 4) {
return "gecko" /* BrowserEngineKind.Gecko */;
}
return "unknown" /* BrowserEngineKind.Unknown */;
}
function getBrowserKind() {
var _a;
var userAgent = (_a = navigator.userAgent) === null || _a === void 0 ? void 0 : _a.toLowerCase();
if (strIncludes(userAgent, 'edg/')) {
return "edge" /* BrowserKind.Edge */;
}
else if (strIncludes(userAgent, 'trident') || strIncludes(userAgent, 'msie')) {
return "internet_explorer" /* BrowserKind.IE */;
}
else if (strIncludes(userAgent, 'wechat')) {
return "wechat" /* BrowserKind.WeChat */;
}
else if (strIncludes(userAgent, 'firefox')) {
return "firefox" /* BrowserKind.Firefox */;
}
else if (strIncludes(userAgent, 'opera') || strIncludes(userAgent, 'opr')) {
return "opera" /* BrowserKind.Opera */;
}
else if (strIncludes(userAgent, 'chrome')) {
return "chrome" /* BrowserKind.Chrome */;
}
else if (strIncludes(userAgent, 'safari')) {
return "safari" /* BrowserKind.Safari */;
}
else {
return "unknown" /* BrowserKind.Unknown */;
}
}
// Source: https://github.com/fingerprintjs/fingerprintjs/blob/master/src/utils/browser.ts#L223
function isAndroid() {
var browserEngineKind = getBrowserEngineKind();
var isItChromium = browserEngineKind === "chromium" /* BrowserEngineKind.Chromium */;
var isItGecko = browserEngineKind === "gecko" /* BrowserEngineKind.Gecko */;
// Only 2 browser engines are presented on Android.
// Actually, there is also Android 4.1 browser, but it's not worth detecting it at the moment.
if (!isItChromium && !isItGecko)
return false;
var w = window;
// Chrome removes all words "Android" from `navigator` when desktop version is requested
// Firefox keeps "Android" in `navigator.appVersion` when desktop version is requested
return (countTruthy([
'onorientationchange' in w,
'orientation' in w,
isItChromium && !('SharedWorker' in w),
isItGecko && /android/i.test(navigator.appVersion),
]) >= 2);
}
function getDocumentFocus() {
if (document.hasFocus === undefined) {
return false;
}
return document.hasFocus();
}
function isChromium86OrNewer() {
// Checked in Chrome 85 vs Chrome 86 both on desktop and Android
var w = window;
return (countTruthy([
!('MediaSettingsRange' in w),
'RTCEncodedAudioFrame' in w,
'' + w.Intl === '[object Intl]',
'' + w.Reflect === '[object Reflect]',
]) >= 3);
}
function getLanguages() {
var n = navigator;
var result = [];
var language = n.language || n.userLanguage || n.browserLanguage || n.systemLanguage;
if (language !== undefined) {
result.push([language]);
}
if (Array.isArray(n.languages)) {
var browserEngine = getBrowserEngineKind();
// Starting from Chromium 86, there is only a single value in `navigator.language` in Incognito mode:
// the value of `navigator.language`. Therefore, the value is ignored in this browser.
if (!(browserEngine === "chromium" /* BrowserEngineKind.Chromium */ && isChromium86OrNewer())) {
result.push(n.languages);
}
}
else if (typeof n.languages === 'string') {
var languages = n.languages;
if (languages) {
result.push(languages.split(','));
}
}
return result;
}
function areMimeTypesConsistent() {
if (navigator.mimeTypes === undefined) {
throw new BotdError(-1 /* State.Undefined */, 'navigator.mimeTypes is undefined');
}
var mimeTypes = navigator.mimeTypes;
var isConsistent = Object.getPrototypeOf(mimeTypes) === MimeTypeArray.prototype;
for (var i = 0; i < mimeTypes.length; i++) {
isConsistent && (isConsistent = Object.getPrototypeOf(mimeTypes[i]) === MimeType.prototype);
}
return isConsistent;
}
function getNotificationPermissions() {
return __awaiter(this, void 0, void 0, function () {
var permissions, permissionStatus;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (window.Notification === undefined) {
throw new BotdError(-1 /* State.Undefined */, 'window.Notification is undefined');
}
if (navigator.permissions === undefined) {
throw new BotdError(-1 /* State.Undefined */, 'navigator.permissions is undefined');
}
permissions = navigator.permissions;
if (typeof permissions.query !== 'function') {
throw new BotdError(-2 /* State.NotFunction */, 'navigator.permissions.query is not a function');
}
_a.label = 1;
case 1:
_a.trys.push([1, 3, , 4]);
return [4 /*yield*/, permissions.query({ name: 'notifications' })];
case 2:
permissionStatus = _a.sent();
return [2 /*return*/, window.Notification.permission === 'denied' && permissionStatus.state === 'prompt'];
case 3:
_a.sent();
throw new BotdError(-3 /* State.UnexpectedBehaviour */, 'notificationPermissions signal unexpected behaviour');
case 4: return [2 /*return*/];
}
});
});
}
function getPluginsArray() {
if (navigator.plugins === undefined) {
throw new BotdError(-1 /* State.Undefined */, 'navigator.plugins is undefined');
}
if (window.PluginArray === undefined) {
throw new BotdError(-1 /* State.Undefined */, 'window.PluginArray is undefined');
}
return navigator.plugins instanceof PluginArray;
}
function getPluginsLength() {
if (navigator.plugins === undefined) {
throw new BotdError(-1 /* State.Undefined */, 'navigator.plugins is undefined');
}
if (navigator.plugins.length === undefined) {
throw new BotdError(-3 /* State.UnexpectedBehaviour */, 'navigator.plugins.length is undefined');
}
return navigator.plugins.length;
}
function getProcess() {
var process = window.process;
var errorPrefix = 'window.process is';
if (process === undefined) {
throw new BotdError(-1 /* State.Undefined */, "".concat(errorPrefix, " undefined"));
}
if (process && typeof process !== 'object') {
throw new BotdError(-3 /* State.UnexpectedBehaviour */, "".concat(errorPrefix, " not an object"));
}
return process;
}
function getProductSub() {
var productSub = navigator.productSub;
if (productSub === undefined) {
throw new BotdError(-1 /* State.Undefined */, 'navigator.productSub is undefined');
}
return productSub;
}
function getRTT() {
if (navigator.connection === undefined) {
throw new BotdError(-1 /* State.Undefined */, 'navigator.connection is undefined');
}
if (navigator.connection.rtt === undefined) {
throw new BotdError(-1 /* State.Undefined */, 'navigator.connection.rtt is undefined');
}
return navigator.connection.rtt;
}
function getUserAgent() {
return navigator.userAgent;
}
function getWebDriver() {
if (navigator.webdriver == undefined) {
throw new BotdError(-1 /* State.Undefined */, 'navigator.webdriver is undefined');
}
return navigator.webdriver;
}
function getWebGL() {
var canvasElement = document.createElement('canvas');
if (typeof canvasElement.getContext !== 'function') {
throw new BotdError(-2 /* State.NotFunction */, 'HTMLCanvasElement.getContext is not a function');
}
var webGLContext = canvasElement.getContext('webgl');
if (webGLContext === null) {
throw new BotdError(-4 /* State.Null */, 'WebGLRenderingContext is null');
}
if (typeof webGLContext.getParameter !== 'function') {
throw new BotdError(-2 /* State.NotFunction */, 'WebGLRenderingContext.getParameter is not a function');
}
var vendor = webGLContext.getParameter(webGLContext.VENDOR);
var renderer = webGLContext.getParameter(webGLContext.RENDERER);
return { vendor: vendor, renderer: renderer };
}
function getWindowExternal() {
if (window.external === undefined) {
throw new BotdError(-1 /* State.Undefined */, 'window.external is undefined');
}
var external = window.external;
if (typeof external.toString !== 'function') {
throw new BotdError(-2 /* State.NotFunction */, 'window.external.toString is not a function');
}
return external.toString();
}
function getWindowSize() {
return {
outerWidth: window.outerWidth,
outerHeight: window.outerHeight,
innerWidth: window.innerWidth,
innerHeight: window.innerHeight,
};
}
function checkDistinctiveProperties() {
var _a;
// The order in the following list matters, because specific types of bots come first, followed by automation technologies.
var distinctivePropsList = (_a = {},
_a[BotKind.Awesomium] = {
window: ['awesomium'],
},
_a[BotKind.Cef] = {
window: ['RunPerfTest'],
},
_a[BotKind.CefSharp] = {
window: ['CefSharp'],
},
_a[BotKind.CoachJS] = {
window: ['emit'],
},
_a[BotKind.FMiner] = {
window: ['fmget_targets'],
},
_a[BotKind.Geb] = {
window: ['geb'],
},
_a[BotKind.NightmareJS] = {
window: ['__nightmare', 'nightmare'],
},
_a[BotKind.Phantomas] = {
window: ['__phantomas'],
},
_a[BotKind.PhantomJS] = {
window: ['callPhantom', '_phantom'],
},
_a[BotKind.Rhino] = {
window: ['spawn'],
},
_a[BotKind.Selenium] = {
window: ['_Selenium_IDE_Recorder', '_selenium', 'calledSelenium', /^([a-z]){3}_.*_(Array|Promise|Symbol)$/],
document: ['__selenium_evaluate', 'selenium-evaluate', '__selenium_unwrapped'],
},
_a[BotKind.WebDriverIO] = {
window: ['wdioElectron'],
},
_a[BotKind.WebDriver] = {
window: [
'webdriver',
'__webdriverFunc',
'__lastWatirAlert',
'__lastWatirConfirm',
'__lastWatirPrompt',
'_WEBDRIVER_ELEM_CACHE',
'ChromeDriverw',
],
document: [
'__webdriver_script_fn',
'__driver_evaluate',
'__webdriver_evaluate',
'__fxdriver_evaluate',
'__driver_unwrapped',
'__webdriver_unwrapped',
'__fxdriver_unwrapped',
'__webdriver_script_fn',
'__webdriver_script_func',
'__webdriver_script_function',
'$cdc_asdjflasutopfhvcZLmcf',
'$cdc_asdjflasutopfhvcZLmcfl_',
'$chrome_asyncScriptInfo',
'__$webdriverAsyncExecutor',
],
},
_a[BotKind.HeadlessChrome] = {
window: ['domAutomation', 'domAutomationController'],
},
_a);
var botName;
var result = {};
var windowProps = getObjectProps(window);
var documentProps = [];
if (window.document !== undefined)
documentProps = getObjectProps(window.document);
for (botName in distinctivePropsList) {
var props = distinctivePropsList[botName];
if (props !== undefined) {
var windowContains = props.window === undefined ? false : includes.apply(void 0, __spreadArray([windowProps], props.window, false));
var documentContains = props.document === undefined || !documentProps.length ? false : includes.apply(void 0, __spreadArray([documentProps], props.document, false));
result[botName] = windowContains || documentContains;
}
}
return result;
}
var sources = {
android: isAndroid,
browserKind: getBrowserKind,
browserEngineKind: getBrowserEngineKind,
documentFocus: getDocumentFocus,
userAgent: getUserAgent,
appVersion: getAppVersion,
rtt: getRTT,
windowSize: getWindowSize,
pluginsLength: getPluginsLength,
pluginsArray: getPluginsArray,
errorTrace: getErrorTrace,
productSub: getProductSub,
windowExternal: getWindowExternal,
mimeTypesConsistent: areMimeTypesConsistent,
evalLength: getEvalLength,
webGL: getWebGL,
webDriver: getWebDriver,
languages: getLanguages,
notificationPermissions: getNotificationPermissions,
documentElementKeys: getDocumentElementKeys,
functionBind: getFunctionBind,
process: getProcess,
distinctiveProps: checkDistinctiveProperties,
};
/**
* Class representing a bot detector.
*
* @class
* @implements {BotDetectorInterface}
*/
var BotDetector = /** @class */ (function () {
function BotDetector() {
this.components = undefined;
this.detections = undefined;
}
BotDetector.prototype.getComponents = function () {
return this.components;
};
BotDetector.prototype.getDetections = function () {
return this.detections;
};
/**
* @inheritdoc
*/
BotDetector.prototype.detect = function () {
if (this.components === undefined) {
throw new Error("BotDetector.detect can't be called before BotDetector.collect");
}
var _a = detect(this.components, detectors), detections = _a[0], finalDetection = _a[1];
this.detections = detections;
return finalDetection;
};
/**
* @inheritdoc
*/
BotDetector.prototype.collect = function () {
return __awaiter(this, void 0, void 0, function () {
var _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
_a = this;
return [4 /*yield*/, collect(sources)];
case 1:
_a.components = _b.sent();
return [2 /*return*/, this.components];
}
});
});
};
return BotDetector;
}());
/**
* Sends an unpersonalized AJAX request to collect installation statistics
*/
function monitor() {
// The FingerprintJS CDN (https://github.com/fingerprintjs/cdn) replaces `window.__fpjs_d_m` with `true`
if (window.__fpjs_d_m || Math.random() >= 0.001) {
return;
}
try {
var request = new XMLHttpRequest();
request.open('get', "https://m1.openfpcdn.io/botd/v".concat(version, "/npm-monitoring"), true);
request.send();
}
catch (error) {
// console.error is ok here because it's an unexpected error handler
// eslint-disable-next-line no-console
console.error(error);
}
}
function load(_a) {
var _b = _a === void 0 ? {} : _a, _c = _b.monitoring, monitoring = _c === void 0 ? true : _c;
return __awaiter(this, void 0, void 0, function () {
var detector;
return __generator(this, function (_d) {
switch (_d.label) {
case 0:
if (monitoring) {
monitor();
}
detector = new BotDetector();
return [4 /*yield*/, detector.collect()];
case 1:
_d.sent();
return [2 /*return*/, detector];
}
});
});
}
var index = { load: load };
export { BotKind, BotdError, collect, index as default, detect, detectors, load, sources };