diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dfe751e..67283da 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -73,3 +73,21 @@ jobs: --extensions=php --ignore=vendor/,sdk/vendor/,build/,dist/ . + + sdk-tests: + name: SDK behaviour and registry parity + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '7.4' + + # Dependency-free: the pure SDK classes, the AI crawler policy, and the + # generated crawler registry replayed against the shared parity vectors. + # A hand edit to the generated table, or a regeneration whose vectors + # were not committed with it, fails here. + - name: Run tests + run: php tests/run.php diff --git a/changelog.txt b/changelog.txt index 80c142f..d46f512 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,11 @@ *** WebDecoy Bot Detection Changelog *** += Unreleased = +* Changed: known crawlers are now identified from the same crawler registry the WebDecoy dashboard and the other WebDecoy sensors use, instead of a list kept only in this plugin. A crawler is named the same thing here and in your reports. The registry knows 182 crawlers where the old list knew 54, so more search engines (Naver, Seznam, Ecosia, Mojeek and others), more AI crawlers (ByteSpider, Mistral, YouBot and others) and more link-preview, monitoring, SEO and feed services are recognised as what they are. +* Changed: with Block AI crawlers on, AI agents and assistants that browse on a person's behalf (for example ChatGPT-User, Claude-User, Operator, Siri) are refused along with training crawlers, and so are the newly recognised AI crawlers above. ChatGPT-User and OAI-SearchBot are now classified as OpenAI documents them (an assistant and a search crawler, neither used for training), which matters once per-path crawler policy arrives; under this setting they are refused either way. The setting is the one instruction about AI traffic; if you want a specific one through, add it to the custom allowlist by name. +* Changed: the W3C markup and Validator.nu checkers are no longer listed as known bots. They were never treated as good bots, so requests from them are scored exactly as before; they simply no longer carry a bot name. +* Internal: the crawler table is generated from WebDecoy/app and replayed against shared parity vectors in CI, so it cannot drift from the other sensors unnoticed. PHP 7.4 compatibility and the SDK behaviour tests now run in CI. + = 2.8.3 - 2026-09-21 = * Fixed: Block AI crawlers is now an explicit decision rather than a scoring hint. The setting worked by withdrawing a recognised AI crawler's good-bot pass and leaving the rest to heuristic scoring. Scoring adds no points for a recognised bot, so a well-behaved AI crawler sending ordinary headers could stay under the block threshold. With the setting on, a recognised AI crawler is now refused whatever it scores, and the Detections page records the reason as ai_crawler_blocked. The custom allowlist still wins, search engines and social bots are unaffected, and in monitor mode the block is counted rather than applied, like every other action. If you rely on this setting, please update. * Internal: added behaviour tests for the AI crawler setting. diff --git a/sdk/src/AgentRegistry.php b/sdk/src/AgentRegistry.php new file mode 100644 index 0000000..f80957e --- /dev/null +++ b/sdk/src/AgentRegistry.php @@ -0,0 +1,114 @@ +|null */ + private static $table = null; + + /** + * Load the generated table once per process. + * + * @return array{schema:int,agent_count:int,categories:list,agents:list>} + */ + private static function table(): array + { + if (self::$table === null) { + $loaded = require __DIR__ . '/registry/agents.generated.php'; + if (!is_array($loaded) || (int) ($loaded['schema'] ?? 0) !== self::SCHEMA) { + throw new \RuntimeException( + 'WebDecoy agent registry schema mismatch: expected ' . self::SCHEMA + . ', found ' . (string) ($loaded['schema'] ?? 'none') + ); + } + self::$table = $loaded; + } + return self::$table; + } + + /** + * Identify the agent a User-Agent claims to be. + * + * A claim, not a verification: the User-Agent header is whatever the + * client chose to send. Callers that need more ask GoodBotList to verify + * the source address. + * + * @return array{id:string,name:string,category:string,behavior:string,organization:string,pattern:string,website:string,robots_name:string}|null + */ + public static function match(string $userAgent): ?array + { + if ($userAgent === '') { + return null; + } + $ua = strtolower($userAgent); + foreach (self::table()['agents'] as $agent) { + foreach ($agent['patterns'] as $pattern) { + if ($pattern !== '' && strpos($ua, $pattern) !== false) { + return [ + 'id' => (string) $agent['id'], + 'name' => (string) $agent['name'], + 'category' => (string) $agent['category'], + 'behavior' => (string) ($agent['behavior'] ?? ''), + 'organization' => (string) $agent['organization'], + 'pattern' => (string) $pattern, + 'website' => (string) $agent['website'], + 'robots_name' => (string) $agent['robots_name'], + ]; + } + } + } + return null; + } + + /** + * Every agent, in match order. + * + * @return list> + */ + public static function all(): array + { + return self::table()['agents']; + } + + /** + * The category vocabulary the table uses (the customer-facing names). + * + * @return list + */ + public static function categories(): array + { + return self::table()['categories']; + } + + /** How many agents the table carries, for drift checks. */ + public static function count(): int + { + return (int) self::table()['agent_count']; + } +} diff --git a/sdk/src/GoodBotList.php b/sdk/src/GoodBotList.php index cc41cd3..7b7fee0 100644 --- a/sdk/src/GoodBotList.php +++ b/sdk/src/GoodBotList.php @@ -39,14 +39,14 @@ class GoodBotList public const CATEGORY_DEVELOPER = 'developer'; /** - * Bots that require IP verification via reverse DNS - * Maps bot pattern to expected hostname suffix(es) + * Bots that require IP verification via reverse DNS, keyed by registry + * agent id, mapped to the hostname suffixes their operators publish. */ private const VERIFIABLE_BOTS = [ 'googlebot' => ['.googlebot.com', '.google.com'], 'google-inspectiontool' => ['.googlebot.com', '.google.com'], 'google-extended' => ['.googlebot.com', '.google.com'], - 'feedfetcher' => ['.google.com'], + 'feedfetcher-google' => ['.google.com'], 'bingbot' => ['.search.msn.com'], 'msnbot' => ['.search.msn.com'], 'yandexbot' => ['.yandex.ru', '.yandex.net', '.yandex.com'], @@ -60,6 +60,30 @@ class GoodBotList 'pinterestbot' => ['.pinterest.com'], ]; + /** + * Registry categories that are good bots here, and which plugin category + * each one lands in. A registry category absent from this map (security + * scanners, scraping frameworks, headless browsers, HTTP clients) is not a + * good bot: identify() returns null for it and the request is scored as + * it always was. + * + * AI agents and assistants join AI crawlers deliberately: the "Block AI + * crawlers" switch is the owner's one instruction about AI traffic, and an + * agent browsing on a person's behalf is still AI traffic. + */ + private const PLUGIN_CATEGORY = [ + 'search_crawler' => self::CATEGORY_SEARCH_ENGINE, + 'ai_search_crawler' => self::CATEGORY_SEARCH_ENGINE, + 'training_crawler' => self::CATEGORY_AI_CRAWLER, + 'ai_agent' => self::CATEGORY_AI_CRAWLER, + 'ai_assistant' => self::CATEGORY_AI_CRAWLER, + 'fetcher' => self::CATEGORY_SOCIAL, + 'monitoring' => self::CATEGORY_MONITORING, + 'seo_crawler' => self::CATEGORY_SEO, + 'feed_reader' => self::CATEGORY_FEED, + 'archiver' => self::CATEGORY_ARCHIVE, + ]; + /** * In-memory cache for verified bot IPs (pattern => [ip => bool]) * Used as fallback when WordPress transients are not available @@ -121,299 +145,6 @@ private function setCachedVerification(string $cacheKey, array $result): void ]; } - /** - * Known good bots with their patterns and categories - * - * Format: 'pattern' => ['name' => '...', 'category' => '...', 'url' => '...'] - */ - private const BOTS = [ - // Search Engines - 'googlebot' => [ - 'name' => 'Googlebot', - 'category' => self::CATEGORY_SEARCH_ENGINE, - 'url' => 'https://developers.google.com/search/docs/crawling-indexing/googlebot', - ], - 'google-inspectiontool' => [ - 'name' => 'Google Inspection Tool', - 'category' => self::CATEGORY_SEARCH_ENGINE, - 'url' => 'https://support.google.com/webmasters/answer/9012289', - ], - 'bingbot' => [ - 'name' => 'Bingbot', - 'category' => self::CATEGORY_SEARCH_ENGINE, - 'url' => 'https://www.bing.com/webmasters/help/which-crawlers-does-bing-use-8c184ec0', - ], - 'msnbot' => [ - 'name' => 'MSNBot', - 'category' => self::CATEGORY_SEARCH_ENGINE, - 'url' => 'https://www.bing.com/webmasters', - ], - 'yandexbot' => [ - 'name' => 'YandexBot', - 'category' => self::CATEGORY_SEARCH_ENGINE, - 'url' => 'https://yandex.com/support/webmaster/robot-workings/check-yandex-robots.html', - ], - 'baiduspider' => [ - 'name' => 'Baiduspider', - 'category' => self::CATEGORY_SEARCH_ENGINE, - 'url' => 'http://www.baidu.com/search/spider.html', - ], - 'duckduckbot' => [ - 'name' => 'DuckDuckBot', - 'category' => self::CATEGORY_SEARCH_ENGINE, - 'url' => 'https://duckduckgo.com/duckduckbot', - ], - 'slurp' => [ - 'name' => 'Yahoo Slurp', - 'category' => self::CATEGORY_SEARCH_ENGINE, - 'url' => 'https://help.yahoo.com/kb/slurp-crawling-page-sln22600.html', - ], - 'sogou' => [ - 'name' => 'Sogou Spider', - 'category' => self::CATEGORY_SEARCH_ENGINE, - 'url' => 'https://www.sogou.com/docs/help/webmasters.htm', - ], - 'exabot' => [ - 'name' => 'Exabot', - 'category' => self::CATEGORY_SEARCH_ENGINE, - 'url' => 'https://www.exalead.com/search/webmasterguide', - ], - 'qwantify' => [ - 'name' => 'Qwantify', - 'category' => self::CATEGORY_SEARCH_ENGINE, - 'url' => 'https://www.qwant.com/', - ], - 'applebot' => [ - 'name' => 'Applebot', - 'category' => self::CATEGORY_SEARCH_ENGINE, - 'url' => 'https://support.apple.com/en-us/HT204683', - ], - - // AI Crawlers - 'gptbot' => [ - 'name' => 'GPTBot', - 'category' => self::CATEGORY_AI_CRAWLER, - 'url' => 'https://platform.openai.com/docs/gptbot', - ], - 'chatgpt-user' => [ - 'name' => 'ChatGPT User', - 'category' => self::CATEGORY_AI_CRAWLER, - 'url' => 'https://platform.openai.com/docs/plugins/bot', - ], - 'oai-searchbot' => [ - 'name' => 'OAI-SearchBot', - 'category' => self::CATEGORY_AI_CRAWLER, - 'url' => 'https://platform.openai.com/', - ], - 'claudebot' => [ - 'name' => 'ClaudeBot', - 'category' => self::CATEGORY_AI_CRAWLER, - 'url' => 'https://www.anthropic.com/', - ], - 'claude-web' => [ - 'name' => 'Claude-Web', - 'category' => self::CATEGORY_AI_CRAWLER, - 'url' => 'https://www.anthropic.com/', - ], - 'anthropic-ai' => [ - 'name' => 'Anthropic-AI', - 'category' => self::CATEGORY_AI_CRAWLER, - 'url' => 'https://www.anthropic.com/', - ], - 'perplexitybot' => [ - 'name' => 'PerplexityBot', - 'category' => self::CATEGORY_AI_CRAWLER, - 'url' => 'https://www.perplexity.ai/', - ], - 'ccbot' => [ - 'name' => 'CCBot', - 'category' => self::CATEGORY_AI_CRAWLER, - 'url' => 'https://commoncrawl.org/ccbot', - ], - 'cohere-ai' => [ - 'name' => 'Cohere-AI', - 'category' => self::CATEGORY_AI_CRAWLER, - 'url' => 'https://cohere.ai/', - ], - 'google-extended' => [ - 'name' => 'Google-Extended', - 'category' => self::CATEGORY_AI_CRAWLER, - 'url' => 'https://developers.google.com/search/docs/crawling-indexing/overview-google-crawlers', - ], - 'meta-externalagent' => [ - 'name' => 'Meta-ExternalAgent', - 'category' => self::CATEGORY_AI_CRAWLER, - 'url' => 'https://developers.facebook.com/', - ], - 'amazonbot' => [ - 'name' => 'Amazonbot', - 'category' => self::CATEGORY_AI_CRAWLER, - 'url' => 'https://developer.amazon.com/amazonbot', - ], - - // Social Media - 'twitterbot' => [ - 'name' => 'Twitterbot', - 'category' => self::CATEGORY_SOCIAL, - 'url' => 'https://developer.twitter.com/en/docs/twitter-for-websites/cards/guides/getting-started', - ], - 'facebookexternalhit' => [ - 'name' => 'Facebook External Hit', - 'category' => self::CATEGORY_SOCIAL, - 'url' => 'https://developers.facebook.com/docs/sharing/webmasters/crawler', - ], - 'facebot' => [ - 'name' => 'Facebot', - 'category' => self::CATEGORY_SOCIAL, - 'url' => 'https://developers.facebook.com/', - ], - 'linkedinbot' => [ - 'name' => 'LinkedInBot', - 'category' => self::CATEGORY_SOCIAL, - 'url' => 'https://www.linkedin.com/', - ], - 'pinterestbot' => [ - 'name' => 'Pinterestbot', - 'category' => self::CATEGORY_SOCIAL, - 'url' => 'https://www.pinterest.com/', - ], - 'slackbot' => [ - 'name' => 'Slackbot', - 'category' => self::CATEGORY_SOCIAL, - 'url' => 'https://api.slack.com/robots', - ], - 'telegrambot' => [ - 'name' => 'TelegramBot', - 'category' => self::CATEGORY_SOCIAL, - 'url' => 'https://telegram.org/', - ], - 'whatsapp' => [ - 'name' => 'WhatsApp', - 'category' => self::CATEGORY_SOCIAL, - 'url' => 'https://www.whatsapp.com/', - ], - 'discordbot' => [ - 'name' => 'Discordbot', - 'category' => self::CATEGORY_SOCIAL, - 'url' => 'https://discord.com/', - ], - 'redditbot' => [ - 'name' => 'Redditbot', - 'category' => self::CATEGORY_SOCIAL, - 'url' => 'https://www.reddit.com/', - ], - - // Monitoring & Uptime - 'pingdom' => [ - 'name' => 'Pingdom', - 'category' => self::CATEGORY_MONITORING, - 'url' => 'https://www.pingdom.com/', - ], - 'uptimerobot' => [ - 'name' => 'UptimeRobot', - 'category' => self::CATEGORY_MONITORING, - 'url' => 'https://uptimerobot.com/', - ], - 'newrelicpinger' => [ - 'name' => 'NewRelicPinger', - 'category' => self::CATEGORY_MONITORING, - 'url' => 'https://newrelic.com/', - ], - 'datadogsynthetics' => [ - 'name' => 'DatadogSynthetics', - 'category' => self::CATEGORY_MONITORING, - 'url' => 'https://www.datadoghq.com/', - ], - 'statuscake' => [ - 'name' => 'StatusCake', - 'category' => self::CATEGORY_MONITORING, - 'url' => 'https://www.statuscake.com/', - ], - 'site24x7' => [ - 'name' => 'Site24x7', - 'category' => self::CATEGORY_MONITORING, - 'url' => 'https://www.site24x7.com/', - ], - 'gtmetrix' => [ - 'name' => 'GTmetrix', - 'category' => self::CATEGORY_MONITORING, - 'url' => 'https://gtmetrix.com/', - ], - 'pagespeed' => [ - 'name' => 'PageSpeed', - 'category' => self::CATEGORY_MONITORING, - 'url' => 'https://pagespeed.web.dev/', - ], - - // SEO Tools - 'semrushbot' => [ - 'name' => 'SemrushBot', - 'category' => self::CATEGORY_SEO, - 'url' => 'https://www.semrush.com/bot/', - ], - 'ahrefsbot' => [ - 'name' => 'AhrefsBot', - 'category' => self::CATEGORY_SEO, - 'url' => 'https://ahrefs.com/robot', - ], - 'mj12bot' => [ - 'name' => 'MJ12bot (Majestic)', - 'category' => self::CATEGORY_SEO, - 'url' => 'https://majestic.com/reports/majestic-bot', - ], - 'dotbot' => [ - 'name' => 'DotBot (Moz)', - 'category' => self::CATEGORY_SEO, - 'url' => 'https://moz.com/help/moz-procedures/crawlers/dotbot', - ], - 'screaming frog' => [ - 'name' => 'Screaming Frog', - 'category' => self::CATEGORY_SEO, - 'url' => 'https://www.screamingfrog.co.uk/', - ], - - // Feed Readers - 'feedfetcher' => [ - 'name' => 'Feedfetcher-Google', - 'category' => self::CATEGORY_FEED, - 'url' => 'https://www.google.com/', - ], - 'feedly' => [ - 'name' => 'Feedly', - 'category' => self::CATEGORY_FEED, - 'url' => 'https://feedly.com/', - ], - 'newsblur' => [ - 'name' => 'NewsBlur', - 'category' => self::CATEGORY_FEED, - 'url' => 'https://newsblur.com/', - ], - - // Archive/Research - 'archive.org_bot' => [ - 'name' => 'Archive.org Bot', - 'category' => self::CATEGORY_ARCHIVE, - 'url' => 'https://archive.org/details/archive.org_bot', - ], - 'ia_archiver' => [ - 'name' => 'Internet Archive', - 'category' => self::CATEGORY_ARCHIVE, - 'url' => 'https://archive.org/', - ], - - // Developer Tools - 'w3c_validator' => [ - 'name' => 'W3C Validator', - 'category' => self::CATEGORY_DEVELOPER, - 'url' => 'https://validator.w3.org/', - ], - 'validator.nu' => [ - 'name' => 'Validator.nu', - 'category' => self::CATEGORY_DEVELOPER, - 'url' => 'https://validator.nu/', - ], - ]; - /** * Identify a bot from User-Agent string * @@ -422,24 +153,37 @@ private function setCachedVerification(string $cacheKey, array $result): void */ public function identify(string $userAgent): ?array { - if (empty($userAgent)) { + $agent = AgentRegistry::match($userAgent); + if ($agent === null) { return null; } + return self::fromAgent($agent); + } - $uaLower = strtolower($userAgent); - - foreach (self::BOTS as $pattern => $info) { - if (strpos($uaLower, $pattern) !== false) { - return [ - 'name' => $info['name'], - 'category' => $info['category'], - 'url' => $info['url'], - 'pattern' => $pattern, - ]; - } + /** + * The plugin's view of a registry agent, or null when the agent is not a + * good bot here. + * + * @param array $agent + * @return array{name:string,category:string,url:string,pattern:string,id:string,behavior:string,registry_category:string}|null + */ + private static function fromAgent(array $agent): ?array + { + $category = self::PLUGIN_CATEGORY[$agent['category']] ?? null; + if ($category === null) { + return null; } - - return null; + return [ + 'name' => (string) $agent['name'], + 'category' => $category, + 'url' => (string) $agent['website'], + 'pattern' => (string) $agent['pattern'], + 'id' => (string) $agent['id'], + // The policy vocabulary (#995): what kind of crawler this is, in + // the words the dashboard's per-path refusals use. + 'behavior' => (string) ($agent['behavior'] ?? ''), + 'registry_category' => (string) $agent['category'], + ]; } /** @@ -485,18 +229,11 @@ public function isAllowed(string $botName, array $policies = []): bool public function getByCategory(string $category): array { $bots = []; - - foreach (self::BOTS as $pattern => $info) { - if ($info['category'] === $category) { - $bots[] = [ - 'name' => $info['name'], - 'category' => $info['category'], - 'url' => $info['url'], - 'pattern' => $pattern, - ]; + foreach ($this->getAllBots() as $bot) { + if ($bot['category'] === $category) { + $bots[] = $bot; } } - return $bots; } @@ -558,16 +295,13 @@ public function getSEOBots(): array public function getAllBots(): array { $bots = []; - - foreach (self::BOTS as $pattern => $info) { - $bots[] = [ - 'name' => $info['name'], - 'category' => $info['category'], - 'url' => $info['url'], - 'pattern' => $pattern, - ]; + foreach (AgentRegistry::all() as $agent) { + $agent['pattern'] = (string) ($agent['patterns'][0] ?? ''); + $bot = self::fromAgent($agent); + if ($bot !== null) { + $bots[] = $bot; + } } - return $bots; } @@ -598,15 +332,12 @@ public function getCategories(): array public function getCategoryCounts(): array { $counts = []; - foreach ($this->getCategories() as $category) { $counts[$category] = 0; } - - foreach (self::BOTS as $info) { - $counts[$info['category']]++; + foreach ($this->getAllBots() as $bot) { + $counts[$bot['category']]++; } - return $counts; } @@ -631,7 +362,7 @@ public function verifyBotIP(string $userAgent, string $ip): array ]; } - $pattern = $bot['pattern']; + $pattern = $bot['id']; // Check if this bot requires IP verification if (!isset(self::VERIFIABLE_BOTS[$pattern])) { @@ -782,30 +513,40 @@ public function identifyAndVerify(string $userAgent, string $ip): ?array 'verified' => $verification['verified'], 'verified_hostname' => $verification['hostname'], 'verification_reason' => $verification['reason'], - 'requires_verification' => isset(self::VERIFIABLE_BOTS[$bot['pattern']]), + 'requires_verification' => isset(self::VERIFIABLE_BOTS[$bot['id']]), ]); } /** - * Check if a specific bot pattern requires IP verification + * Check if a bot requires IP verification. * - * @param string $pattern The bot pattern + * Takes the registry agent id, or a User-Agent pattern for callers that + * still hold the matched pattern from identify(). + * + * @param string $key The registry id or the matched pattern * @return bool */ - public function requiresVerification(string $pattern): bool + public function requiresVerification(string $key): bool { - return isset(self::VERIFIABLE_BOTS[$pattern]); + return $this->getExpectedHostnames($key) !== null; } /** - * Get the expected hostname suffixes for a bot pattern + * Get the expected hostname suffixes for a bot. * - * @param string $pattern The bot pattern + * @param string $key The registry id or the matched pattern * @return array|null List of expected suffixes, or null if verification not required */ - public function getExpectedHostnames(string $pattern): ?array + public function getExpectedHostnames(string $key): ?array { - return self::VERIFIABLE_BOTS[$pattern] ?? null; + if (isset(self::VERIFIABLE_BOTS[$key])) { + return self::VERIFIABLE_BOTS[$key]; + } + $agent = AgentRegistry::match($key); + if ($agent !== null && isset(self::VERIFIABLE_BOTS[$agent['id']])) { + return self::VERIFIABLE_BOTS[$agent['id']]; + } + return null; } /** diff --git a/sdk/src/registry/agents.generated.php b/sdk/src/registry/agents.generated.php new file mode 100644 index 0000000..0456cf7 --- /dev/null +++ b/sdk/src/registry/agents.generated.php @@ -0,0 +1,2387 @@ + 2, + 'agent_count' => 182, + 'categories' => ['training_crawler', 'ai_search_crawler', 'ai_agent', 'ai_assistant', 'search_crawler', 'seo_crawler', 'security_scanner', 'generic_scraper', 'archiver', 'fetcher', 'monitoring', 'headless_browser', 'feed_reader', 'commercial_scraper', 'none'], + 'agents' => [ + [ + 'id' => 'reflectionbot', + 'name' => 'Reflectionbot', + 'category' => 'training_crawler', + 'behavior' => 'training', + 'organization' => 'Reflection AI', + 'patterns' => ['reflectionbot'], + 'robots_name' => 'Reflectionbot', + 'website' => 'https://reflection.ai', + 'base_score' => 70, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'gptbot', + 'name' => 'GPTBot', + 'category' => 'training_crawler', + 'behavior' => 'training', + 'organization' => 'OpenAI', + 'patterns' => ['gptbot'], + 'robots_name' => 'GPTBot', + 'website' => 'https://platform.openai.com/docs/gptbot', + 'base_score' => 85, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'claudebot', + 'name' => 'ClaudeBot', + 'category' => 'training_crawler', + 'behavior' => 'training', + 'organization' => 'Anthropic', + 'patterns' => ['claudebot'], + 'robots_name' => 'ClaudeBot', + 'website' => 'https://www.anthropic.com', + 'base_score' => 85, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'anthropic', + 'name' => 'Anthropic', + 'category' => 'training_crawler', + 'behavior' => 'training', + 'organization' => 'Anthropic', + 'patterns' => ['anthropic'], + 'robots_name' => 'anthropic', + 'website' => 'https://www.anthropic.com', + 'base_score' => 85, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'claude-web', + 'name' => 'Claude-Web', + 'category' => 'training_crawler', + 'behavior' => 'training', + 'organization' => 'Anthropic', + 'patterns' => ['claude-web'], + 'robots_name' => 'Claude-Web', + 'website' => 'https://www.anthropic.com', + 'base_score' => 85, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'ccbot', + 'name' => 'CCBot', + 'category' => 'training_crawler', + 'behavior' => 'training', + 'organization' => 'Common Crawl', + 'patterns' => ['ccbot'], + 'robots_name' => 'CCBot', + 'website' => 'https://commoncrawl.org', + 'base_score' => 80, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'google-extended', + 'name' => 'Google-Extended', + 'category' => 'training_crawler', + 'behavior' => 'training', + 'organization' => 'Google', + 'patterns' => ['google-extended'], + 'robots_name' => 'Google-Extended', + 'website' => 'https://developers.google.com/search/docs/crawling-indexing/google-extended', + 'base_score' => 80, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'bytespider', + 'name' => 'ByteSpider', + 'category' => 'training_crawler', + 'behavior' => 'training', + 'organization' => 'ByteDance', + 'patterns' => ['bytespider'], + 'robots_name' => 'Bytespider', + 'website' => 'https://bytedance.com', + 'base_score' => 75, + 'respects_robots' => false, + 'http_client' => false, + ], + [ + 'id' => 'amazonbot', + 'name' => 'Amazonbot', + 'category' => 'training_crawler', + 'behavior' => 'training', + 'organization' => 'Amazon', + 'patterns' => ['amazonbot'], + 'robots_name' => 'Amazonbot', + 'website' => 'https://developer.amazon.com/amazonbot', + 'base_score' => 70, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'facebookbot', + 'name' => 'FacebookBot', + 'category' => 'training_crawler', + 'behavior' => 'training', + 'organization' => 'Meta', + 'patterns' => ['facebookbot'], + 'robots_name' => 'FacebookBot', + 'website' => 'https://developers.facebook.com', + 'base_score' => 70, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'meta-externalagent', + 'name' => 'Meta-ExternalAgent', + 'category' => 'training_crawler', + 'behavior' => 'training', + 'organization' => 'Meta', + 'patterns' => ['meta-externalagent'], + 'robots_name' => 'Meta-ExternalAgent', + 'website' => 'https://meta.com', + 'base_score' => 75, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'cohere-ai', + 'name' => 'Cohere', + 'category' => 'training_crawler', + 'behavior' => 'training', + 'organization' => 'Cohere', + 'patterns' => ['cohere-ai', 'cohere'], + 'robots_name' => 'cohere-ai', + 'website' => 'https://cohere.ai', + 'base_score' => 80, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'perplexitybot', + 'name' => 'PerplexityBot', + 'category' => 'training_crawler', + 'behavior' => 'training', + 'organization' => 'Perplexity AI', + 'patterns' => ['perplexitybot'], + 'robots_name' => 'PerplexityBot', + 'website' => 'https://perplexity.ai', + 'base_score' => 80, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'applebot-extended', + 'name' => 'Applebot-Extended', + 'category' => 'training_crawler', + 'behavior' => 'training', + 'organization' => 'Apple', + 'patterns' => ['applebot-extended'], + 'robots_name' => 'Applebot-Extended', + 'website' => 'https://support.apple.com/applebot', + 'base_score' => 75, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'youbot', + 'name' => 'YouBot', + 'category' => 'training_crawler', + 'behavior' => 'training', + 'organization' => 'You.com', + 'patterns' => ['youbot'], + 'robots_name' => 'YouBot', + 'website' => 'https://you.com', + 'base_score' => 75, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'mistral', + 'name' => 'MistralBot', + 'category' => 'training_crawler', + 'behavior' => 'training', + 'organization' => 'Mistral AI', + 'patterns' => ['mistral'], + 'robots_name' => 'MistralBot', + 'website' => 'https://mistral.ai', + 'base_score' => 80, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'gemini', + 'name' => 'Gemini', + 'category' => 'training_crawler', + 'behavior' => 'training', + 'organization' => 'Google', + 'patterns' => ['gemini'], + 'robots_name' => 'Gemini', + 'website' => 'https://deepmind.google', + 'base_score' => 80, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'ai2bot', + 'name' => 'AI2Bot', + 'category' => 'training_crawler', + 'behavior' => 'training', + 'organization' => 'Allen Institute for AI', + 'patterns' => ['ai2bot'], + 'robots_name' => 'AI2Bot', + 'website' => 'https://allenai.org', + 'base_score' => 75, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'deepseek', + 'name' => 'DeepSeek', + 'category' => 'training_crawler', + 'behavior' => 'training', + 'organization' => 'DeepSeek', + 'patterns' => ['deepseek'], + 'robots_name' => 'DeepSeek', + 'website' => 'https://deepseek.com', + 'base_score' => 80, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'qwen', + 'name' => 'Qwen', + 'category' => 'training_crawler', + 'behavior' => 'training', + 'organization' => 'Alibaba', + 'patterns' => ['qwen'], + 'robots_name' => 'Qwen', + 'website' => 'https://qwenlm.github.io', + 'base_score' => 75, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'webzio', + 'name' => 'Webz.io', + 'category' => 'training_crawler', + 'behavior' => 'training', + 'organization' => 'Webz.io', + 'patterns' => ['webzio'], + 'robots_name' => 'webzio', + 'website' => 'https://webz.io', + 'base_score' => 70, + 'respects_robots' => false, + 'http_client' => false, + ], + [ + 'id' => 'sentibot', + 'name' => 'Sentibot', + 'category' => 'training_crawler', + 'behavior' => 'training', + 'organization' => 'Sentibot', + 'patterns' => ['sentibot'], + 'robots_name' => 'Sentibot', + 'website' => '', + 'base_score' => 70, + 'respects_robots' => false, + 'http_client' => false, + ], + [ + 'id' => 'omgili', + 'name' => 'Omgili', + 'category' => 'training_crawler', + 'behavior' => 'training', + 'organization' => 'Webz.io', + 'patterns' => ['omgili'], + 'robots_name' => 'omgili', + 'website' => 'https://omgili.com', + 'base_score' => 70, + 'respects_robots' => false, + 'http_client' => false, + ], + [ + 'id' => 'img2dataset', + 'name' => 'img2dataset', + 'category' => 'training_crawler', + 'behavior' => 'training', + 'organization' => 'LAION', + 'patterns' => ['img2dataset'], + 'robots_name' => 'img2dataset', + 'website' => 'https://github.com/rom1504/img2dataset', + 'base_score' => 75, + 'respects_robots' => false, + 'http_client' => false, + ], + [ + 'id' => 'timpibot', + 'name' => 'Timpibot', + 'category' => 'training_crawler', + 'behavior' => 'training', + 'organization' => 'Timpi', + 'patterns' => ['timpibot'], + 'robots_name' => 'Timpibot', + 'website' => 'https://timpi.io', + 'base_score' => 70, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'velenpublicwebcrawler', + 'name' => 'VelenPublicWebCrawler', + 'category' => 'training_crawler', + 'behavior' => 'training', + 'organization' => 'Velen', + 'patterns' => ['velenpublicwebcrawler'], + 'robots_name' => 'VelenPublicWebCrawler', + 'website' => '', + 'base_score' => 70, + 'respects_robots' => false, + 'http_client' => false, + ], + [ + 'id' => 'isscyberriskcrawler', + 'name' => 'ISSCyberRiskCrawler', + 'category' => 'training_crawler', + 'behavior' => 'training', + 'organization' => 'ISS', + 'patterns' => ['isscyberriskcrawler'], + 'robots_name' => 'ISSCyberRiskCrawler', + 'website' => '', + 'base_score' => 65, + 'respects_robots' => false, + 'http_client' => false, + ], + [ + 'id' => 'friendlycrawler', + 'name' => 'FriendlyCrawler', + 'category' => 'training_crawler', + 'behavior' => 'training', + 'organization' => 'Unknown', + 'patterns' => ['friendlycrawler'], + 'robots_name' => 'FriendlyCrawler', + 'website' => '', + 'base_score' => 65, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'duckassistbot', + 'name' => 'DuckAssistBot', + 'category' => 'ai_search_crawler', + 'behavior' => 'search', + 'organization' => 'DuckDuckGo', + 'patterns' => ['duckassistbot'], + 'robots_name' => 'DuckAssistBot', + 'website' => 'https://duckduckgo.com/duckassistbot.html', + 'base_score' => 65, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'sofyabot', + 'name' => 'SofyaBot', + 'category' => 'ai_search_crawler', + 'behavior' => 'search', + 'organization' => 'Sofya', + 'patterns' => ['sofyabot'], + 'robots_name' => 'SofyaBot', + 'website' => 'https://sofya.co/bot', + 'base_score' => 65, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'xai-searchbot', + 'name' => 'xAI-SearchBot', + 'category' => 'ai_search_crawler', + 'behavior' => 'search', + 'organization' => 'xAI', + 'patterns' => ['xai-searchbot'], + 'robots_name' => 'xAI-SearchBot', + 'website' => 'https://x.ai', + 'base_score' => 70, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'linkupbot', + 'name' => 'LinkupBot', + 'category' => 'ai_search_crawler', + 'behavior' => 'search', + 'organization' => 'Linkup', + 'patterns' => ['linkupbot'], + 'robots_name' => 'LinkupBot', + 'website' => 'https://linkup.so/bot', + 'base_score' => 65, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'oai-searchbot', + 'name' => 'OAI-SearchBot', + 'category' => 'ai_search_crawler', + 'behavior' => 'search', + 'organization' => 'OpenAI', + 'patterns' => ['oai-searchbot'], + 'robots_name' => 'OAI-SearchBot', + 'website' => 'https://openai.com', + 'base_score' => 80, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'searchgpt', + 'name' => 'SearchGPT', + 'category' => 'ai_search_crawler', + 'behavior' => 'search', + 'organization' => 'OpenAI', + 'patterns' => ['searchgpt'], + 'robots_name' => 'SearchGPT', + 'website' => 'https://openai.com', + 'base_score' => 75, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'phind', + 'name' => 'Phind', + 'category' => 'ai_search_crawler', + 'behavior' => 'search', + 'organization' => 'Phind', + 'patterns' => ['phind'], + 'robots_name' => 'Phind', + 'website' => 'https://phind.com', + 'base_score' => 70, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'kagi', + 'name' => 'Kagi', + 'category' => 'ai_search_crawler', + 'behavior' => 'search', + 'organization' => 'Kagi', + 'patterns' => ['kagi'], + 'robots_name' => 'Kagi', + 'website' => 'https://kagi.com', + 'base_score' => 65, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'exa', + 'name' => 'Exa', + 'category' => 'ai_search_crawler', + 'behavior' => 'search', + 'organization' => 'Exa AI', + 'patterns' => ['exa.ai', 'exabot'], + 'robots_name' => 'Exa', + 'website' => 'https://exa.ai', + 'base_score' => 70, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'metaphor', + 'name' => 'Metaphor', + 'category' => 'ai_search_crawler', + 'behavior' => 'search', + 'organization' => 'Metaphor', + 'patterns' => ['metaphor'], + 'robots_name' => 'Metaphor', + 'website' => 'https://metaphor.systems', + 'base_score' => 70, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'tavily', + 'name' => 'Tavily', + 'category' => 'ai_search_crawler', + 'behavior' => 'search', + 'organization' => 'Tavily', + 'patterns' => ['tavily'], + 'robots_name' => 'Tavily', + 'website' => 'https://tavily.com', + 'base_score' => 70, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'brave-search', + 'name' => 'BraveSearch', + 'category' => 'ai_search_crawler', + 'behavior' => 'search', + 'organization' => 'Brave', + 'patterns' => ['bravesearch'], + 'robots_name' => 'BraveSearch', + 'website' => 'https://search.brave.com', + 'base_score' => 65, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'neeva', + 'name' => 'NeevaBot', + 'category' => 'ai_search_crawler', + 'behavior' => 'search', + 'organization' => 'Neeva', + 'patterns' => ['neevabot'], + 'robots_name' => 'NeevaBot', + 'website' => 'https://neeva.com', + 'base_score' => 65, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'operator', + 'name' => 'Operator', + 'category' => 'ai_agent', + 'behavior' => 'agent', + 'organization' => 'OpenAI', + 'patterns' => ['operator'], + 'robots_name' => 'Operator', + 'website' => 'https://openai.com', + 'base_score' => 75, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'claude-user', + 'name' => 'Claude-User', + 'category' => 'ai_agent', + 'behavior' => 'agent', + 'organization' => 'Anthropic', + 'patterns' => ['claude-user'], + 'robots_name' => 'Claude-User', + 'website' => 'https://anthropic.com', + 'base_score' => 75, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'gemini-user', + 'name' => 'Gemini-User', + 'category' => 'ai_agent', + 'behavior' => 'agent', + 'organization' => 'Google', + 'patterns' => ['gemini-user'], + 'robots_name' => 'Gemini-User', + 'website' => 'https://gemini.google.com', + 'base_score' => 75, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'googleagent-mariner', + 'name' => 'GoogleAgent-Mariner', + 'category' => 'ai_agent', + 'behavior' => 'agent', + 'organization' => 'Google', + 'patterns' => ['googleagent-mariner', 'mariner'], + 'robots_name' => 'GoogleAgent-Mariner', + 'website' => 'https://deepmind.google', + 'base_score' => 75, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'amazon-buyforme', + 'name' => 'AmazonBuyForMe', + 'category' => 'ai_agent', + 'behavior' => 'agent', + 'organization' => 'Amazon', + 'patterns' => ['amazonbuyforme', 'buyforme'], + 'robots_name' => 'AmazonBuyForMe', + 'website' => 'https://amazon.com', + 'base_score' => 70, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'browser-use', + 'name' => 'Browser-Use', + 'category' => 'ai_agent', + 'behavior' => 'agent', + 'organization' => 'Open Source', + 'patterns' => ['browser-use'], + 'robots_name' => 'Browser-Use', + 'website' => 'https://github.com/browser-use/browser-use', + 'base_score' => 70, + 'respects_robots' => false, + 'http_client' => false, + ], + [ + 'id' => 'stagehand', + 'name' => 'Stagehand', + 'category' => 'ai_agent', + 'behavior' => 'agent', + 'organization' => 'Browserbase', + 'patterns' => ['stagehand'], + 'robots_name' => 'Stagehand', + 'website' => 'https://browserbase.com', + 'base_score' => 70, + 'respects_robots' => false, + 'http_client' => false, + ], + [ + 'id' => 'multion', + 'name' => 'MultiOn', + 'category' => 'ai_agent', + 'behavior' => 'agent', + 'organization' => 'MultiOn', + 'patterns' => ['multion'], + 'robots_name' => 'MultiOn', + 'website' => 'https://multion.ai', + 'base_score' => 70, + 'respects_robots' => false, + 'http_client' => false, + ], + [ + 'id' => 'iboubot', + 'name' => 'IbouBot', + 'category' => 'search_crawler', + 'behavior' => 'search', + 'organization' => 'Ibou', + 'patterns' => ['iboubot'], + 'robots_name' => 'IbouBot', + 'website' => 'https://ibou.io/iboubot.html', + 'base_score' => 30, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'googlebot', + 'name' => 'Googlebot', + 'category' => 'search_crawler', + 'behavior' => 'search', + 'organization' => 'Google', + 'patterns' => ['googlebot'], + 'robots_name' => 'Googlebot', + 'website' => 'https://developers.google.com/search/docs/crawling-indexing/googlebot', + 'base_score' => 30, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'google-inspectiontool', + 'name' => 'Google-InspectionTool', + 'category' => 'search_crawler', + 'behavior' => 'search', + 'organization' => 'Google', + 'patterns' => ['google-inspectiontool'], + 'robots_name' => 'Google-InspectionTool', + 'website' => 'https://developers.google.com/search/docs/crawling-indexing/google-common-crawlers', + 'base_score' => 30, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'bingbot', + 'name' => 'Bingbot', + 'category' => 'search_crawler', + 'behavior' => 'search', + 'organization' => 'Microsoft', + 'patterns' => ['bingbot'], + 'robots_name' => 'Bingbot', + 'website' => 'https://www.bing.com/webmasters/help/bingbot', + 'base_score' => 30, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'msnbot', + 'name' => 'MSNBot', + 'category' => 'search_crawler', + 'behavior' => 'search', + 'organization' => 'Microsoft', + 'patterns' => ['msnbot'], + 'robots_name' => 'msnbot', + 'website' => 'https://www.bing.com/webmasters/help/which-crawlers-does-bing-use-8c184ec0', + 'base_score' => 30, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'yandexbot', + 'name' => 'YandexBot', + 'category' => 'search_crawler', + 'behavior' => 'search', + 'organization' => 'Yandex', + 'patterns' => ['yandexbot'], + 'robots_name' => 'YandexBot', + 'website' => 'https://yandex.com/support/webmaster/robot-workings/', + 'base_score' => 35, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'baiduspider', + 'name' => 'Baiduspider', + 'category' => 'search_crawler', + 'behavior' => 'search', + 'organization' => 'Baidu', + 'patterns' => ['baiduspider'], + 'robots_name' => 'Baiduspider', + 'website' => 'https://www.baidu.com/search/spider.html', + 'base_score' => 40, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'duckduckbot', + 'name' => 'DuckDuckBot', + 'category' => 'search_crawler', + 'behavior' => 'search', + 'organization' => 'DuckDuckGo', + 'patterns' => ['duckduckbot'], + 'robots_name' => 'DuckDuckBot', + 'website' => 'https://duckduckgo.com/duckduckbot', + 'base_score' => 30, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'applebot', + 'name' => 'Applebot', + 'category' => 'search_crawler', + 'behavior' => 'search', + 'organization' => 'Apple', + 'patterns' => ['applebot'], + 'robots_name' => 'Applebot', + 'website' => 'https://support.apple.com/applebot', + 'base_score' => 30, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'sogou', + 'name' => 'Sogou Spider', + 'category' => 'search_crawler', + 'behavior' => 'search', + 'organization' => 'Sogou', + 'patterns' => ['sogou'], + 'robots_name' => 'Sogou', + 'website' => 'https://sogou.com', + 'base_score' => 40, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'qwantify', + 'name' => 'Qwantify', + 'category' => 'search_crawler', + 'behavior' => 'search', + 'organization' => 'Qwant', + 'patterns' => ['qwantify'], + 'robots_name' => 'Qwantify', + 'website' => 'https://qwant.com', + 'base_score' => 35, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'naver', + 'name' => 'Naver', + 'category' => 'search_crawler', + 'behavior' => 'search', + 'organization' => 'Naver', + 'patterns' => ['naver', 'yeti'], + 'robots_name' => 'Naver', + 'website' => 'https://naver.com', + 'base_score' => 35, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'seznam', + 'name' => 'SeznamBot', + 'category' => 'search_crawler', + 'behavior' => 'search', + 'organization' => 'Seznam', + 'patterns' => ['seznambot'], + 'robots_name' => 'SeznamBot', + 'website' => 'https://seznam.cz', + 'base_score' => 35, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'ecosia', + 'name' => 'Ecosia', + 'category' => 'search_crawler', + 'behavior' => 'search', + 'organization' => 'Ecosia', + 'patterns' => ['ecosia'], + 'robots_name' => 'Ecosia', + 'website' => 'https://ecosia.org', + 'base_score' => 30, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'mojeek', + 'name' => 'MojeekBot', + 'category' => 'search_crawler', + 'behavior' => 'search', + 'organization' => 'Mojeek', + 'patterns' => ['mojeekbot'], + 'robots_name' => 'MojeekBot', + 'website' => 'https://mojeek.com', + 'base_score' => 35, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'yahoo-slurp', + 'name' => 'Yahoo! Slurp', + 'category' => 'search_crawler', + 'behavior' => 'search', + 'organization' => 'Yahoo', + 'patterns' => ['slurp'], + 'robots_name' => 'Slurp', + 'website' => 'https://yahoo.com', + 'base_score' => 30, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'ahrefsbot', + 'name' => 'AhrefsBot', + 'category' => 'seo_crawler', + 'behavior' => 'seo', + 'organization' => 'Ahrefs', + 'patterns' => ['ahrefsbot', 'ahrefs'], + 'robots_name' => 'AhrefsBot', + 'website' => 'https://ahrefs.com/robot', + 'base_score' => 50, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'semrushbot', + 'name' => 'SemrushBot', + 'category' => 'seo_crawler', + 'behavior' => 'seo', + 'organization' => 'Semrush', + 'patterns' => ['semrushbot', 'semrush'], + 'robots_name' => 'SemrushBot', + 'website' => 'https://semrush.com/bot', + 'base_score' => 50, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'mj12bot', + 'name' => 'MJ12bot', + 'category' => 'seo_crawler', + 'behavior' => 'seo', + 'organization' => 'Majestic', + 'patterns' => ['mj12bot'], + 'robots_name' => 'MJ12bot', + 'website' => 'https://majestic.com/bot', + 'base_score' => 50, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'dotbot', + 'name' => 'DotBot', + 'category' => 'seo_crawler', + 'behavior' => 'seo', + 'organization' => 'Moz', + 'patterns' => ['dotbot'], + 'robots_name' => 'DotBot', + 'website' => 'https://moz.com/help/moz-procedures/crawlers', + 'base_score' => 50, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'rogerbot', + 'name' => 'Rogerbot', + 'category' => 'seo_crawler', + 'behavior' => 'seo', + 'organization' => 'Moz', + 'patterns' => ['rogerbot'], + 'robots_name' => 'rogerbot', + 'website' => 'https://moz.com/help/moz-procedures/crawlers', + 'base_score' => 50, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'screaming-frog', + 'name' => 'Screaming Frog', + 'category' => 'seo_crawler', + 'behavior' => 'seo', + 'organization' => 'Screaming Frog', + 'patterns' => ['screaming frog'], + 'robots_name' => 'Screaming Frog SEO Spider', + 'website' => 'https://screamingfrog.co.uk', + 'base_score' => 55, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'sitebulb', + 'name' => 'Sitebulb', + 'category' => 'seo_crawler', + 'behavior' => 'seo', + 'organization' => 'Sitebulb', + 'patterns' => ['sitebulb'], + 'robots_name' => 'Sitebulb', + 'website' => 'https://sitebulb.com', + 'base_score' => 55, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'deepcrawl', + 'name' => 'DeepCrawl', + 'category' => 'seo_crawler', + 'behavior' => 'seo', + 'organization' => 'Lumar', + 'patterns' => ['deepcrawl'], + 'robots_name' => 'DeepCrawl', + 'website' => 'https://lumar.io', + 'base_score' => 50, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'oncrawl', + 'name' => 'OnCrawl', + 'category' => 'seo_crawler', + 'behavior' => 'seo', + 'organization' => 'OnCrawl', + 'patterns' => ['oncrawl'], + 'robots_name' => 'OnCrawl', + 'website' => 'https://oncrawl.com', + 'base_score' => 50, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'botify', + 'name' => 'Botify', + 'category' => 'seo_crawler', + 'behavior' => 'seo', + 'organization' => 'Botify', + 'patterns' => ['botify'], + 'robots_name' => 'Botify', + 'website' => 'https://botify.com', + 'base_score' => 50, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'contentking', + 'name' => 'ContentKing', + 'category' => 'seo_crawler', + 'behavior' => 'seo', + 'organization' => 'ContentKing', + 'patterns' => ['contentking'], + 'robots_name' => 'ContentKing', + 'website' => 'https://contentkingapp.com', + 'base_score' => 50, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'sistrix', + 'name' => 'SISTRIX', + 'category' => 'seo_crawler', + 'behavior' => 'seo', + 'organization' => 'SISTRIX', + 'patterns' => ['sistrix'], + 'robots_name' => 'SISTRIX', + 'website' => 'https://sistrix.com', + 'base_score' => 50, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'serpstat', + 'name' => 'Serpstat', + 'category' => 'seo_crawler', + 'behavior' => 'seo', + 'organization' => 'Serpstat', + 'patterns' => ['serpstat'], + 'robots_name' => 'Serpstat', + 'website' => 'https://serpstat.com', + 'base_score' => 50, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'spyfu', + 'name' => 'SpyFu', + 'category' => 'seo_crawler', + 'behavior' => 'seo', + 'organization' => 'SpyFu', + 'patterns' => ['spyfu'], + 'robots_name' => 'SpyFu', + 'website' => 'https://spyfu.com', + 'base_score' => 50, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'nessus', + 'name' => 'Nessus', + 'category' => 'security_scanner', + 'behavior' => 'security_testing', + 'organization' => 'Tenable', + 'patterns' => ['nessus'], + 'robots_name' => 'Nessus', + 'website' => 'https://tenable.com', + 'base_score' => 70, + 'respects_robots' => false, + 'http_client' => false, + ], + [ + 'id' => 'qualys', + 'name' => 'Qualys', + 'category' => 'security_scanner', + 'behavior' => 'security_testing', + 'organization' => 'Qualys', + 'patterns' => ['qualys'], + 'robots_name' => 'Qualys', + 'website' => 'https://qualys.com', + 'base_score' => 70, + 'respects_robots' => false, + 'http_client' => false, + ], + [ + 'id' => 'shodan', + 'name' => 'Shodan', + 'category' => 'security_scanner', + 'behavior' => 'security_testing', + 'organization' => 'Shodan', + 'patterns' => ['shodan'], + 'robots_name' => 'Shodan', + 'website' => 'https://shodan.io', + 'base_score' => 75, + 'respects_robots' => false, + 'http_client' => false, + ], + [ + 'id' => 'censys', + 'name' => 'Censys', + 'category' => 'security_scanner', + 'behavior' => 'security_testing', + 'organization' => 'Censys', + 'patterns' => ['censys'], + 'robots_name' => 'Censys', + 'website' => 'https://censys.io', + 'base_score' => 75, + 'respects_robots' => false, + 'http_client' => false, + ], + [ + 'id' => 'nmap', + 'name' => 'Nmap', + 'category' => 'security_scanner', + 'behavior' => 'security_testing', + 'organization' => 'Open Source', + 'patterns' => ['nmap'], + 'robots_name' => 'Nmap', + 'website' => 'https://nmap.org', + 'base_score' => 70, + 'respects_robots' => false, + 'http_client' => false, + ], + [ + 'id' => 'zap', + 'name' => 'OWASP ZAP', + 'category' => 'security_scanner', + 'behavior' => 'security_testing', + 'organization' => 'OWASP', + 'patterns' => ['zap/'], + 'robots_name' => 'ZAP', + 'website' => 'https://zaproxy.org', + 'base_score' => 70, + 'respects_robots' => false, + 'http_client' => false, + ], + [ + 'id' => 'burp', + 'name' => 'Burp Suite', + 'category' => 'security_scanner', + 'behavior' => 'security_testing', + 'organization' => 'PortSwigger', + 'patterns' => ['burp'], + 'robots_name' => 'Burp', + 'website' => 'https://portswigger.net/burp', + 'base_score' => 70, + 'respects_robots' => false, + 'http_client' => false, + ], + [ + 'id' => 'nikto', + 'name' => 'Nikto', + 'category' => 'security_scanner', + 'behavior' => 'security_testing', + 'organization' => 'Open Source', + 'patterns' => ['nikto'], + 'robots_name' => 'Nikto', + 'website' => 'https://cirt.net/Nikto2', + 'base_score' => 70, + 'respects_robots' => false, + 'http_client' => false, + ], + [ + 'id' => 'nuclei', + 'name' => 'Nuclei', + 'category' => 'security_scanner', + 'behavior' => 'security_testing', + 'organization' => 'ProjectDiscovery', + 'patterns' => ['nuclei'], + 'robots_name' => 'Nuclei', + 'website' => 'https://nuclei.projectdiscovery.io', + 'base_score' => 70, + 'respects_robots' => false, + 'http_client' => false, + ], + [ + 'id' => 'acunetix', + 'name' => 'Acunetix', + 'category' => 'security_scanner', + 'behavior' => 'security_testing', + 'organization' => 'Invicti', + 'patterns' => ['acunetix'], + 'robots_name' => 'Acunetix', + 'website' => 'https://acunetix.com', + 'base_score' => 70, + 'respects_robots' => false, + 'http_client' => false, + ], + [ + 'id' => 'netsparker', + 'name' => 'Netsparker', + 'category' => 'security_scanner', + 'behavior' => 'security_testing', + 'organization' => 'Invicti', + 'patterns' => ['netsparker'], + 'robots_name' => 'Netsparker', + 'website' => 'https://netsparker.com', + 'base_score' => 70, + 'respects_robots' => false, + 'http_client' => false, + ], + [ + 'id' => 'detectify', + 'name' => 'Detectify', + 'category' => 'security_scanner', + 'behavior' => 'security_testing', + 'organization' => 'Detectify', + 'patterns' => ['detectify'], + 'robots_name' => 'Detectify', + 'website' => 'https://detectify.com', + 'base_score' => 65, + 'respects_robots' => false, + 'http_client' => false, + ], + [ + 'id' => 'intruder', + 'name' => 'Intruder', + 'category' => 'security_scanner', + 'behavior' => 'security_testing', + 'organization' => 'Intruder', + 'patterns' => ['intruder'], + 'robots_name' => 'Intruder', + 'website' => 'https://intruder.io', + 'base_score' => 65, + 'respects_robots' => false, + 'http_client' => false, + ], + [ + 'id' => 'python-requests', + 'name' => 'Python-Requests', + 'category' => 'generic_scraper', + 'behavior' => '', + 'organization' => 'Open Source', + 'patterns' => ['python-requests'], + 'robots_name' => '', + 'website' => 'https://requests.readthedocs.io', + 'base_score' => 55, + 'respects_robots' => false, + 'http_client' => true, + ], + [ + 'id' => 'python-urllib', + 'name' => 'Python-urllib', + 'category' => 'generic_scraper', + 'behavior' => '', + 'organization' => 'Python', + 'patterns' => ['python-urllib'], + 'robots_name' => '', + 'website' => 'https://docs.python.org/3/library/urllib.html', + 'base_score' => 55, + 'respects_robots' => false, + 'http_client' => true, + ], + [ + 'id' => 'python', + 'name' => 'Python', + 'category' => 'generic_scraper', + 'behavior' => '', + 'organization' => 'Python', + 'patterns' => ['python/'], + 'robots_name' => '', + 'website' => 'https://python.org', + 'base_score' => 50, + 'respects_robots' => false, + 'http_client' => true, + ], + [ + 'id' => 'scrapy', + 'name' => 'Scrapy', + 'category' => 'generic_scraper', + 'behavior' => '', + 'organization' => 'Scrapy', + 'patterns' => ['scrapy'], + 'robots_name' => 'Scrapy', + 'website' => 'https://scrapy.org', + 'base_score' => 65, + 'respects_robots' => true, + 'http_client' => true, + ], + [ + 'id' => 'httpx', + 'name' => 'HTTPX', + 'category' => 'generic_scraper', + 'behavior' => '', + 'organization' => 'Open Source', + 'patterns' => ['httpx'], + 'robots_name' => '', + 'website' => 'https://www.python-httpx.org', + 'base_score' => 55, + 'respects_robots' => false, + 'http_client' => true, + ], + [ + 'id' => 'aiohttp', + 'name' => 'aiohttp', + 'category' => 'generic_scraper', + 'behavior' => '', + 'organization' => 'Open Source', + 'patterns' => ['aiohttp'], + 'robots_name' => '', + 'website' => 'https://docs.aiohttp.org', + 'base_score' => 55, + 'respects_robots' => false, + 'http_client' => true, + ], + [ + 'id' => 'beautifulsoup', + 'name' => 'BeautifulSoup', + 'category' => 'generic_scraper', + 'behavior' => '', + 'organization' => 'Open Source', + 'patterns' => ['beautifulsoup'], + 'robots_name' => '', + 'website' => 'https://beautiful-soup-4.readthedocs.io', + 'base_score' => 60, + 'respects_robots' => false, + 'http_client' => true, + ], + [ + 'id' => 'node-fetch', + 'name' => 'node-fetch', + 'category' => 'generic_scraper', + 'behavior' => '', + 'organization' => 'Open Source', + 'patterns' => ['node-fetch'], + 'robots_name' => '', + 'website' => 'https://github.com/node-fetch/node-fetch', + 'base_score' => 55, + 'respects_robots' => false, + 'http_client' => true, + ], + [ + 'id' => 'axios', + 'name' => 'Axios', + 'category' => 'generic_scraper', + 'behavior' => '', + 'organization' => 'Open Source', + 'patterns' => ['axios/'], + 'robots_name' => '', + 'website' => 'https://axios-http.com', + 'base_score' => 55, + 'respects_robots' => false, + 'http_client' => true, + ], + [ + 'id' => 'got', + 'name' => 'Got', + 'category' => 'generic_scraper', + 'behavior' => '', + 'organization' => 'Open Source', + 'patterns' => ['got/'], + 'robots_name' => '', + 'website' => 'https://github.com/sindresorhus/got', + 'base_score' => 55, + 'respects_robots' => false, + 'http_client' => true, + ], + [ + 'id' => 'undici', + 'name' => 'Undici', + 'category' => 'generic_scraper', + 'behavior' => '', + 'organization' => 'Node.js', + 'patterns' => ['undici'], + 'robots_name' => '', + 'website' => 'https://undici.nodejs.org', + 'base_score' => 55, + 'respects_robots' => false, + 'http_client' => true, + ], + [ + 'id' => 'go-http-client', + 'name' => 'Go-HTTP-Client', + 'category' => 'generic_scraper', + 'behavior' => '', + 'organization' => 'Go', + 'patterns' => ['go-http-client'], + 'robots_name' => '', + 'website' => 'https://golang.org', + 'base_score' => 55, + 'respects_robots' => false, + 'http_client' => true, + ], + [ + 'id' => 'colly', + 'name' => 'Colly', + 'category' => 'generic_scraper', + 'behavior' => '', + 'organization' => 'Open Source', + 'patterns' => ['colly'], + 'robots_name' => 'Colly', + 'website' => 'https://go-colly.org', + 'base_score' => 65, + 'respects_robots' => true, + 'http_client' => true, + ], + [ + 'id' => 'java', + 'name' => 'Java', + 'category' => 'generic_scraper', + 'behavior' => '', + 'organization' => 'Oracle', + 'patterns' => ['java/'], + 'robots_name' => '', + 'website' => 'https://java.com', + 'base_score' => 50, + 'respects_robots' => false, + 'http_client' => true, + ], + [ + 'id' => 'okhttp', + 'name' => 'OkHttp', + 'category' => 'generic_scraper', + 'behavior' => '', + 'organization' => 'Square', + 'patterns' => ['okhttp'], + 'robots_name' => '', + 'website' => 'https://square.github.io/okhttp/', + 'base_score' => 55, + 'respects_robots' => false, + 'http_client' => true, + ], + [ + 'id' => 'apache-httpclient', + 'name' => 'Apache-HttpClient', + 'category' => 'generic_scraper', + 'behavior' => '', + 'organization' => 'Apache', + 'patterns' => ['apache-httpclient'], + 'robots_name' => '', + 'website' => 'https://hc.apache.org', + 'base_score' => 55, + 'respects_robots' => false, + 'http_client' => true, + ], + [ + 'id' => 'jsoup', + 'name' => 'Jsoup', + 'category' => 'generic_scraper', + 'behavior' => '', + 'organization' => 'Open Source', + 'patterns' => ['jsoup'], + 'robots_name' => '', + 'website' => 'https://jsoup.org', + 'base_score' => 60, + 'respects_robots' => false, + 'http_client' => true, + ], + [ + 'id' => 'guzzlehttp', + 'name' => 'GuzzleHttp', + 'category' => 'generic_scraper', + 'behavior' => '', + 'organization' => 'Open Source', + 'patterns' => ['guzzlehttp'], + 'robots_name' => '', + 'website' => 'https://docs.guzzlephp.org', + 'base_score' => 55, + 'respects_robots' => false, + 'http_client' => true, + ], + [ + 'id' => 'php', + 'name' => 'PHP', + 'category' => 'generic_scraper', + 'behavior' => '', + 'organization' => 'PHP', + 'patterns' => ['php/'], + 'robots_name' => '', + 'website' => 'https://php.net', + 'base_score' => 50, + 'respects_robots' => false, + 'http_client' => true, + ], + [ + 'id' => 'ruby', + 'name' => 'Ruby', + 'category' => 'generic_scraper', + 'behavior' => '', + 'organization' => 'Ruby', + 'patterns' => ['ruby'], + 'robots_name' => '', + 'website' => 'https://ruby-lang.org', + 'base_score' => 50, + 'respects_robots' => false, + 'http_client' => true, + ], + [ + 'id' => 'faraday', + 'name' => 'Faraday', + 'category' => 'generic_scraper', + 'behavior' => '', + 'organization' => 'Open Source', + 'patterns' => ['faraday'], + 'robots_name' => '', + 'website' => 'https://lostisland.github.io/faraday/', + 'base_score' => 55, + 'respects_robots' => false, + 'http_client' => true, + ], + [ + 'id' => 'mechanize', + 'name' => 'Mechanize', + 'category' => 'generic_scraper', + 'behavior' => '', + 'organization' => 'Open Source', + 'patterns' => ['mechanize'], + 'robots_name' => '', + 'website' => '', + 'base_score' => 60, + 'respects_robots' => false, + 'http_client' => true, + ], + [ + 'id' => 'headlesschrome', + 'name' => 'HeadlessChrome', + 'category' => 'headless_browser', + 'behavior' => '', + 'organization' => 'Google', + 'patterns' => ['headlesschrome'], + 'robots_name' => '', + 'website' => 'https://developers.google.com/web/updates/2017/04/headless-chrome', + 'base_score' => 70, + 'respects_robots' => false, + 'http_client' => true, + ], + [ + 'id' => 'puppeteer', + 'name' => 'Puppeteer', + 'category' => 'headless_browser', + 'behavior' => '', + 'organization' => 'Google', + 'patterns' => ['puppeteer'], + 'robots_name' => '', + 'website' => 'https://pptr.dev', + 'base_score' => 70, + 'respects_robots' => false, + 'http_client' => true, + ], + [ + 'id' => 'playwright', + 'name' => 'Playwright', + 'category' => 'headless_browser', + 'behavior' => '', + 'organization' => 'Microsoft', + 'patterns' => ['playwright'], + 'robots_name' => '', + 'website' => 'https://playwright.dev', + 'base_score' => 70, + 'respects_robots' => false, + 'http_client' => true, + ], + [ + 'id' => 'selenium', + 'name' => 'Selenium', + 'category' => 'headless_browser', + 'behavior' => '', + 'organization' => 'Open Source', + 'patterns' => ['selenium'], + 'robots_name' => '', + 'website' => 'https://selenium.dev', + 'base_score' => 70, + 'respects_robots' => false, + 'http_client' => true, + ], + [ + 'id' => 'phantomjs', + 'name' => 'PhantomJS', + 'category' => 'headless_browser', + 'behavior' => '', + 'organization' => 'Open Source', + 'patterns' => ['phantomjs'], + 'robots_name' => '', + 'website' => 'https://phantomjs.org', + 'base_score' => 75, + 'respects_robots' => false, + 'http_client' => true, + ], + [ + 'id' => 'splash', + 'name' => 'Splash', + 'category' => 'headless_browser', + 'behavior' => '', + 'organization' => 'Scrapinghub', + 'patterns' => ['splash'], + 'robots_name' => '', + 'website' => 'https://splash.readthedocs.io', + 'base_score' => 70, + 'respects_robots' => false, + 'http_client' => true, + ], + [ + 'id' => 'browserless', + 'name' => 'Browserless', + 'category' => 'headless_browser', + 'behavior' => '', + 'organization' => 'Browserless', + 'patterns' => ['browserless'], + 'robots_name' => '', + 'website' => 'https://browserless.io', + 'base_score' => 65, + 'respects_robots' => false, + 'http_client' => true, + ], + [ + 'id' => 'browserbase', + 'name' => 'Browserbase', + 'category' => 'headless_browser', + 'behavior' => '', + 'organization' => 'Browserbase', + 'patterns' => ['browserbase'], + 'robots_name' => '', + 'website' => 'https://browserbase.com', + 'base_score' => 65, + 'respects_robots' => false, + 'http_client' => true, + ], + [ + 'id' => 'ia-archiver', + 'name' => 'Internet Archive', + 'category' => 'archiver', + 'behavior' => 'other', + 'organization' => 'Internet Archive', + 'patterns' => ['ia_archiver'], + 'robots_name' => 'ia_archiver', + 'website' => 'https://archive.org', + 'base_score' => 25, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'archive-org-bot', + 'name' => 'Archive.org', + 'category' => 'archiver', + 'behavior' => 'other', + 'organization' => 'Internet Archive', + 'patterns' => ['archive.org_bot'], + 'robots_name' => 'archive.org_bot', + 'website' => 'https://archive.org', + 'base_score' => 25, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'wayback', + 'name' => 'Wayback Machine', + 'category' => 'archiver', + 'behavior' => 'other', + 'organization' => 'Internet Archive', + 'patterns' => ['wayback'], + 'robots_name' => 'Wayback', + 'website' => 'https://web.archive.org', + 'base_score' => 25, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'heritrix', + 'name' => 'Heritrix', + 'category' => 'archiver', + 'behavior' => 'other', + 'organization' => 'Internet Archive', + 'patterns' => ['heritrix'], + 'robots_name' => 'Heritrix', + 'website' => 'https://github.com/internetarchive/heritrix3', + 'base_score' => 30, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'brozzler', + 'name' => 'Brozzler', + 'category' => 'archiver', + 'behavior' => 'other', + 'organization' => 'Internet Archive', + 'patterns' => ['brozzler'], + 'robots_name' => 'Brozzler', + 'website' => 'https://github.com/internetarchive/brozzler', + 'base_score' => 30, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'facebookexternalhit', + 'name' => 'Facebook', + 'category' => 'fetcher', + 'behavior' => 'link_preview', + 'organization' => 'Meta', + 'patterns' => ['facebookexternalhit'], + 'robots_name' => 'facebookexternalhit', + 'website' => 'https://developers.facebook.com/docs/sharing/webmasters/crawler', + 'base_score' => 25, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'facebot', + 'name' => 'Facebot', + 'category' => 'fetcher', + 'behavior' => 'link_preview', + 'organization' => 'Meta', + 'patterns' => ['facebot'], + 'robots_name' => 'Facebot', + 'website' => 'https://developers.facebook.com/docs/sharing/webmasters/crawler', + 'base_score' => 25, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'twitterbot', + 'name' => 'Twitterbot', + 'category' => 'fetcher', + 'behavior' => 'link_preview', + 'organization' => 'X Corp', + 'patterns' => ['twitterbot'], + 'robots_name' => 'Twitterbot', + 'website' => 'https://developer.twitter.com', + 'base_score' => 25, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'linkedinbot', + 'name' => 'LinkedInBot', + 'category' => 'fetcher', + 'behavior' => 'link_preview', + 'organization' => 'LinkedIn', + 'patterns' => ['linkedinbot'], + 'robots_name' => 'LinkedInBot', + 'website' => 'https://linkedin.com', + 'base_score' => 25, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'slackbot', + 'name' => 'Slackbot', + 'category' => 'fetcher', + 'behavior' => 'link_preview', + 'organization' => 'Slack', + 'patterns' => ['slackbot'], + 'robots_name' => 'Slackbot', + 'website' => 'https://api.slack.com/robots', + 'base_score' => 25, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'telegrambot', + 'name' => 'TelegramBot', + 'category' => 'fetcher', + 'behavior' => 'link_preview', + 'organization' => 'Telegram', + 'patterns' => ['telegrambot'], + 'robots_name' => 'TelegramBot', + 'website' => 'https://telegram.org', + 'base_score' => 25, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'whatsapp', + 'name' => 'WhatsApp', + 'category' => 'fetcher', + 'behavior' => 'link_preview', + 'organization' => 'Meta', + 'patterns' => ['whatsapp'], + 'robots_name' => 'WhatsApp', + 'website' => 'https://whatsapp.com', + 'base_score' => 25, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'discordbot', + 'name' => 'Discordbot', + 'category' => 'fetcher', + 'behavior' => 'link_preview', + 'organization' => 'Discord', + 'patterns' => ['discordbot'], + 'robots_name' => 'Discordbot', + 'website' => 'https://discord.com', + 'base_score' => 25, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'pinterestbot', + 'name' => 'Pinterest', + 'category' => 'fetcher', + 'behavior' => 'link_preview', + 'organization' => 'Pinterest', + 'patterns' => ['pinterest'], + 'robots_name' => 'Pinterest', + 'website' => 'https://pinterest.com', + 'base_score' => 30, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'tumblr', + 'name' => 'Tumblr', + 'category' => 'fetcher', + 'behavior' => 'link_preview', + 'organization' => 'Automattic', + 'patterns' => ['tumblr'], + 'robots_name' => 'Tumblr', + 'website' => 'https://tumblr.com', + 'base_score' => 30, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'reddit', + 'name' => 'Reddit', + 'category' => 'fetcher', + 'behavior' => 'link_preview', + 'organization' => 'Reddit', + 'patterns' => ['reddit'], + 'robots_name' => 'Redditbot', + 'website' => 'https://reddit.com', + 'base_score' => 30, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'embedly', + 'name' => 'Embedly', + 'category' => 'fetcher', + 'behavior' => 'link_preview', + 'organization' => 'Medium', + 'patterns' => ['embedly'], + 'robots_name' => 'Embedly', + 'website' => 'https://embed.ly', + 'base_score' => 30, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'iframely', + 'name' => 'Iframely', + 'category' => 'fetcher', + 'behavior' => 'link_preview', + 'organization' => 'Iframely', + 'patterns' => ['iframely'], + 'robots_name' => 'Iframely', + 'website' => 'https://iframely.com', + 'base_score' => 30, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'curl', + 'name' => 'cURL', + 'category' => 'fetcher', + 'behavior' => 'link_preview', + 'organization' => 'Open Source', + 'patterns' => ['curl/'], + 'robots_name' => '', + 'website' => 'https://curl.se', + 'base_score' => 45, + 'respects_robots' => false, + 'http_client' => true, + ], + [ + 'id' => 'wget', + 'name' => 'Wget', + 'category' => 'fetcher', + 'behavior' => 'link_preview', + 'organization' => 'GNU', + 'patterns' => ['wget/'], + 'robots_name' => '', + 'website' => 'https://www.gnu.org/software/wget/', + 'base_score' => 45, + 'respects_robots' => false, + 'http_client' => true, + ], + [ + 'id' => 'libwww-perl', + 'name' => 'libwww-perl', + 'category' => 'fetcher', + 'behavior' => 'link_preview', + 'organization' => 'Perl', + 'patterns' => ['libwww-perl'], + 'robots_name' => '', + 'website' => 'https://metacpan.org/pod/LWP', + 'base_score' => 50, + 'respects_robots' => false, + 'http_client' => true, + ], + [ + 'id' => 'lwp', + 'name' => 'LWP', + 'category' => 'fetcher', + 'behavior' => 'link_preview', + 'organization' => 'Perl', + 'patterns' => ['lwp-'], + 'robots_name' => '', + 'website' => 'https://metacpan.org/pod/LWP::UserAgent', + 'base_score' => 50, + 'respects_robots' => false, + 'http_client' => true, + ], + [ + 'id' => 'httrack', + 'name' => 'HTTrack', + 'category' => 'fetcher', + 'behavior' => 'link_preview', + 'organization' => 'Open Source', + 'patterns' => ['httrack'], + 'robots_name' => 'HTTrack', + 'website' => 'https://httrack.com', + 'base_score' => 60, + 'respects_robots' => true, + 'http_client' => true, + ], + [ + 'id' => 'webdecoybot', + 'name' => 'WebDecoyBot', + 'category' => 'monitoring', + 'behavior' => 'monitoring', + 'organization' => 'WebDecoy', + 'patterns' => ['webdecoybot'], + 'robots_name' => 'WebDecoyBot', + 'website' => 'https://bot.webdecoy.com', + 'base_score' => 5, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'uptimerobot', + 'name' => 'UptimeRobot', + 'category' => 'monitoring', + 'behavior' => 'monitoring', + 'organization' => 'UptimeRobot', + 'patterns' => ['uptimerobot'], + 'robots_name' => 'UptimeRobot', + 'website' => 'https://uptimerobot.com', + 'base_score' => 20, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'pingdom', + 'name' => 'Pingdom', + 'category' => 'monitoring', + 'behavior' => 'monitoring', + 'organization' => 'SolarWinds', + 'patterns' => ['pingdom'], + 'robots_name' => 'Pingdom', + 'website' => 'https://pingdom.com', + 'base_score' => 20, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'statuscake', + 'name' => 'StatusCake', + 'category' => 'monitoring', + 'behavior' => 'monitoring', + 'organization' => 'StatusCake', + 'patterns' => ['statuscake'], + 'robots_name' => 'StatusCake', + 'website' => 'https://statuscake.com', + 'base_score' => 20, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'better-uptime', + 'name' => 'Better Uptime', + 'category' => 'monitoring', + 'behavior' => 'monitoring', + 'organization' => 'Better Stack', + 'patterns' => ['betteruptime'], + 'robots_name' => 'Better Uptime', + 'website' => 'https://betteruptime.com', + 'base_score' => 20, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'datadog-synthetics', + 'name' => 'Datadog Synthetics', + 'category' => 'monitoring', + 'behavior' => 'monitoring', + 'organization' => 'Datadog', + 'patterns' => ['datadog'], + 'robots_name' => 'Datadog', + 'website' => 'https://datadoghq.com', + 'base_score' => 25, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'newrelic', + 'name' => 'New Relic', + 'category' => 'monitoring', + 'behavior' => 'monitoring', + 'organization' => 'New Relic', + 'patterns' => ['newrelic'], + 'robots_name' => 'NewRelic', + 'website' => 'https://newrelic.com', + 'base_score' => 25, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'site24x7', + 'name' => 'Site24x7', + 'category' => 'monitoring', + 'behavior' => 'monitoring', + 'organization' => 'Zoho', + 'patterns' => ['site24x7'], + 'robots_name' => 'Site24x7', + 'website' => 'https://site24x7.com', + 'base_score' => 20, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'freshping', + 'name' => 'Freshping', + 'category' => 'monitoring', + 'behavior' => 'monitoring', + 'organization' => 'Freshworks', + 'patterns' => ['freshping'], + 'robots_name' => 'Freshping', + 'website' => 'https://freshping.io', + 'base_score' => 20, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'hetrixtools', + 'name' => 'HetrixTools', + 'category' => 'monitoring', + 'behavior' => 'monitoring', + 'organization' => 'HetrixTools', + 'patterns' => ['hetrixtools'], + 'robots_name' => 'HetrixTools', + 'website' => 'https://hetrixtools.com', + 'base_score' => 20, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'nodeping', + 'name' => 'NodePing', + 'category' => 'monitoring', + 'behavior' => 'monitoring', + 'organization' => 'NodePing', + 'patterns' => ['nodeping'], + 'robots_name' => 'NodePing', + 'website' => 'https://nodeping.com', + 'base_score' => 20, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'gtmetrix', + 'name' => 'GTmetrix', + 'category' => 'monitoring', + 'behavior' => 'monitoring', + 'organization' => 'GTmetrix', + 'patterns' => ['gtmetrix'], + 'robots_name' => 'GTmetrix', + 'website' => 'https://gtmetrix.com', + 'base_score' => 20, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'chrome-lighthouse', + 'name' => 'Lighthouse', + 'category' => 'monitoring', + 'behavior' => 'monitoring', + 'organization' => 'Google', + 'patterns' => ['chrome-lighthouse', 'google page speed'], + 'robots_name' => 'Chrome-Lighthouse', + 'website' => 'https://developers.google.com/speed/pagespeed/insights/', + 'base_score' => 20, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'feedly', + 'name' => 'Feedly', + 'category' => 'feed_reader', + 'behavior' => 'feeds', + 'organization' => 'Feedly', + 'patterns' => ['feedly'], + 'robots_name' => 'Feedly', + 'website' => 'https://feedly.com', + 'base_score' => 25, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'feedfetcher-google', + 'name' => 'Feedfetcher-Google', + 'category' => 'feed_reader', + 'behavior' => 'feeds', + 'organization' => 'Google', + 'patterns' => ['feedfetcher'], + 'robots_name' => 'FeedFetcher-Google', + 'website' => 'https://developers.google.com/search/docs/crawling-indexing/google-common-crawlers', + 'base_score' => 25, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'newsblur', + 'name' => 'NewsBlur', + 'category' => 'feed_reader', + 'behavior' => 'feeds', + 'organization' => 'NewsBlur', + 'patterns' => ['newsblur'], + 'robots_name' => 'NewsBlur', + 'website' => 'https://newsblur.com', + 'base_score' => 25, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'inoreader', + 'name' => 'Inoreader', + 'category' => 'feed_reader', + 'behavior' => 'feeds', + 'organization' => 'Inoreader', + 'patterns' => ['inoreader'], + 'robots_name' => 'Inoreader', + 'website' => 'https://inoreader.com', + 'base_score' => 25, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'theoldreader', + 'name' => 'The Old Reader', + 'category' => 'feed_reader', + 'behavior' => 'feeds', + 'organization' => 'The Old Reader', + 'patterns' => ['theoldreader'], + 'robots_name' => 'The Old Reader', + 'website' => 'https://theoldreader.com', + 'base_score' => 25, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'feedbin', + 'name' => 'Feedbin', + 'category' => 'feed_reader', + 'behavior' => 'feeds', + 'organization' => 'Feedbin', + 'patterns' => ['feedbin'], + 'robots_name' => 'Feedbin', + 'website' => 'https://feedbin.com', + 'base_score' => 25, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'miniflux', + 'name' => 'Miniflux', + 'category' => 'feed_reader', + 'behavior' => 'feeds', + 'organization' => 'Open Source', + 'patterns' => ['miniflux'], + 'robots_name' => 'Miniflux', + 'website' => 'https://miniflux.app', + 'base_score' => 25, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'freshrss', + 'name' => 'FreshRSS', + 'category' => 'feed_reader', + 'behavior' => 'feeds', + 'organization' => 'Open Source', + 'patterns' => ['freshrss'], + 'robots_name' => 'FreshRSS', + 'website' => 'https://freshrss.org', + 'base_score' => 25, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'commafeed', + 'name' => 'CommaFeed', + 'category' => 'feed_reader', + 'behavior' => 'feeds', + 'organization' => 'Open Source', + 'patterns' => ['commafeed'], + 'robots_name' => 'CommaFeed', + 'website' => 'https://commafeed.com', + 'base_score' => 25, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'diffbot', + 'name' => 'Diffbot', + 'category' => 'commercial_scraper', + 'behavior' => '', + 'organization' => 'Diffbot', + 'patterns' => ['diffbot'], + 'robots_name' => 'Diffbot', + 'website' => 'https://diffbot.com', + 'base_score' => 70, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'import-io', + 'name' => 'Import.io', + 'category' => 'commercial_scraper', + 'behavior' => '', + 'organization' => 'Import.io', + 'patterns' => ['import.io'], + 'robots_name' => 'Import.io', + 'website' => 'https://import.io', + 'base_score' => 65, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'bright-data', + 'name' => 'Bright Data', + 'category' => 'commercial_scraper', + 'behavior' => '', + 'organization' => 'Bright Data', + 'patterns' => ['brightdata', 'luminati'], + 'robots_name' => 'BrightData', + 'website' => 'https://brightdata.com', + 'base_score' => 70, + 'respects_robots' => false, + 'http_client' => false, + ], + [ + 'id' => 'oxylabs', + 'name' => 'Oxylabs', + 'category' => 'commercial_scraper', + 'behavior' => '', + 'organization' => 'Oxylabs', + 'patterns' => ['oxylabs'], + 'robots_name' => 'Oxylabs', + 'website' => 'https://oxylabs.io', + 'base_score' => 70, + 'respects_robots' => false, + 'http_client' => false, + ], + [ + 'id' => 'scrapingbee', + 'name' => 'ScrapingBee', + 'category' => 'commercial_scraper', + 'behavior' => '', + 'organization' => 'ScrapingBee', + 'patterns' => ['scrapingbee'], + 'robots_name' => 'ScrapingBee', + 'website' => 'https://scrapingbee.com', + 'base_score' => 65, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'scrapingant', + 'name' => 'ScrapingAnt', + 'category' => 'commercial_scraper', + 'behavior' => '', + 'organization' => 'ScrapingAnt', + 'patterns' => ['scrapingant'], + 'robots_name' => 'ScrapingAnt', + 'website' => 'https://scrapingant.com', + 'base_score' => 65, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'zyte', + 'name' => 'Zyte', + 'category' => 'commercial_scraper', + 'behavior' => '', + 'organization' => 'Zyte', + 'patterns' => ['zyte', 'scrapinghub'], + 'robots_name' => 'Zyte', + 'website' => 'https://zyte.com', + 'base_score' => 65, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'apify', + 'name' => 'Apify', + 'category' => 'commercial_scraper', + 'behavior' => '', + 'organization' => 'Apify', + 'patterns' => ['apify'], + 'robots_name' => 'Apify', + 'website' => 'https://apify.com', + 'base_score' => 65, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'crawlbase', + 'name' => 'Crawlbase', + 'category' => 'commercial_scraper', + 'behavior' => '', + 'organization' => 'Crawlbase', + 'patterns' => ['crawlbase'], + 'robots_name' => 'Crawlbase', + 'website' => 'https://crawlbase.com', + 'base_score' => 65, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'webscrapingapi', + 'name' => 'WebScrapingAPI', + 'category' => 'commercial_scraper', + 'behavior' => '', + 'organization' => 'WebScrapingAPI', + 'patterns' => ['webscrapingapi'], + 'robots_name' => 'WebScrapingAPI', + 'website' => 'https://webscrapingapi.com', + 'base_score' => 65, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'chatgpt-user', + 'name' => 'ChatGPT-User', + 'category' => 'ai_assistant', + 'behavior' => 'agent', + 'organization' => 'OpenAI', + 'patterns' => ['chatgpt-user', 'chatgpt'], + 'robots_name' => 'ChatGPT-User', + 'website' => 'https://openai.com', + 'base_score' => 85, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'gemini-deep-research', + 'name' => 'Gemini-Deep-Research', + 'category' => 'ai_assistant', + 'behavior' => 'agent', + 'organization' => 'Google', + 'patterns' => ['gemini-deep-research'], + 'robots_name' => 'Gemini-Deep-Research', + 'website' => 'https://gemini.google.com', + 'base_score' => 65, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'copilot', + 'name' => 'Microsoft Copilot', + 'category' => 'ai_assistant', + 'behavior' => 'agent', + 'organization' => 'Microsoft', + 'patterns' => ['copilot'], + 'robots_name' => 'Copilot', + 'website' => 'https://copilot.microsoft.com', + 'base_score' => 65, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'cortana', + 'name' => 'Cortana', + 'category' => 'ai_assistant', + 'behavior' => 'agent', + 'organization' => 'Microsoft', + 'patterns' => ['cortana'], + 'robots_name' => 'Cortana', + 'website' => 'https://microsoft.com', + 'base_score' => 60, + 'respects_robots' => true, + 'http_client' => false, + ], + [ + 'id' => 'siri', + 'name' => 'Siri', + 'category' => 'ai_assistant', + 'behavior' => 'agent', + 'organization' => 'Apple', + 'patterns' => ['siri'], + 'robots_name' => 'Siri', + 'website' => 'https://apple.com', + 'base_score' => 60, + 'respects_robots' => true, + 'http_client' => false, + ], + ], +]; diff --git a/sdk/src/registry/parity-vectors.generated.json b/sdk/src/registry/parity-vectors.generated.json new file mode 100644 index 0000000..8332f95 --- /dev/null +++ b/sdk/src/registry/parity-vectors.generated.json @@ -0,0 +1,2334 @@ +[ + { + "userAgent": "ai2bot", + "id": "ai2bot", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; ai2bot/1.0; +http://example.com/bot)", + "id": "ai2bot", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "acunetix", + "id": "acunetix", + "category": "security_scanner", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; acunetix/1.0; +http://example.com/bot)", + "id": "acunetix", + "category": "security_scanner", + "matched": true + }, + { + "userAgent": "ahrefsbot", + "id": "ahrefsbot", + "category": "seo_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; ahrefsbot/1.0; +http://example.com/bot)", + "id": "ahrefsbot", + "category": "seo_crawler", + "matched": true + }, + { + "userAgent": "ahrefs", + "id": "ahrefsbot", + "category": "seo_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; ahrefs/1.0; +http://example.com/bot)", + "id": "ahrefsbot", + "category": "seo_crawler", + "matched": true + }, + { + "userAgent": "amazonbuyforme", + "id": "amazon-buyforme", + "category": "ai_agent", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; amazonbuyforme/1.0; +http://example.com/bot)", + "id": "amazon-buyforme", + "category": "ai_agent", + "matched": true + }, + { + "userAgent": "buyforme", + "id": "amazon-buyforme", + "category": "ai_agent", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; buyforme/1.0; +http://example.com/bot)", + "id": "amazon-buyforme", + "category": "ai_agent", + "matched": true + }, + { + "userAgent": "amazonbot", + "id": "amazonbot", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; amazonbot/1.0; +http://example.com/bot)", + "id": "amazonbot", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "anthropic", + "id": "anthropic", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; anthropic/1.0; +http://example.com/bot)", + "id": "anthropic", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "apache-httpclient", + "id": "apache-httpclient", + "category": "generic_scraper", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; apache-httpclient/1.0; +http://example.com/bot)", + "id": "apache-httpclient", + "category": "generic_scraper", + "matched": true + }, + { + "userAgent": "apify", + "id": "apify", + "category": "commercial_scraper", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; apify/1.0; +http://example.com/bot)", + "id": "apify", + "category": "commercial_scraper", + "matched": true + }, + { + "userAgent": "applebot", + "id": "applebot", + "category": "search_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; applebot/1.0; +http://example.com/bot)", + "id": "applebot", + "category": "search_crawler", + "matched": true + }, + { + "userAgent": "applebot-extended", + "id": "applebot-extended", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; applebot-extended/1.0; +http://example.com/bot)", + "id": "applebot-extended", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "archive.org_bot", + "id": "archive-org-bot", + "category": "archiver", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; archive.org_bot/1.0; +http://example.com/bot)", + "id": "archive-org-bot", + "category": "archiver", + "matched": true + }, + { + "userAgent": "axios/", + "id": "axios", + "category": "generic_scraper", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; axios//1.0; +http://example.com/bot)", + "id": "axios", + "category": "generic_scraper", + "matched": true + }, + { + "userAgent": "baiduspider", + "id": "baiduspider", + "category": "search_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; baiduspider/1.0; +http://example.com/bot)", + "id": "baiduspider", + "category": "search_crawler", + "matched": true + }, + { + "userAgent": "beautifulsoup", + "id": "beautifulsoup", + "category": "generic_scraper", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; beautifulsoup/1.0; +http://example.com/bot)", + "id": "beautifulsoup", + "category": "generic_scraper", + "matched": true + }, + { + "userAgent": "betteruptime", + "id": "better-uptime", + "category": "monitoring", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; betteruptime/1.0; +http://example.com/bot)", + "id": "better-uptime", + "category": "monitoring", + "matched": true + }, + { + "userAgent": "bingbot", + "id": "bingbot", + "category": "search_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; bingbot/1.0; +http://example.com/bot)", + "id": "bingbot", + "category": "search_crawler", + "matched": true + }, + { + "userAgent": "botify", + "id": "botify", + "category": "seo_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; botify/1.0; +http://example.com/bot)", + "id": "botify", + "category": "seo_crawler", + "matched": true + }, + { + "userAgent": "bravesearch", + "id": "brave-search", + "category": "ai_search_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; bravesearch/1.0; +http://example.com/bot)", + "id": "brave-search", + "category": "ai_search_crawler", + "matched": true + }, + { + "userAgent": "brightdata", + "id": "bright-data", + "category": "commercial_scraper", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; brightdata/1.0; +http://example.com/bot)", + "id": "bright-data", + "category": "commercial_scraper", + "matched": true + }, + { + "userAgent": "luminati", + "id": "bright-data", + "category": "commercial_scraper", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; luminati/1.0; +http://example.com/bot)", + "id": "bright-data", + "category": "commercial_scraper", + "matched": true + }, + { + "userAgent": "browser-use", + "id": "browser-use", + "category": "ai_agent", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; browser-use/1.0; +http://example.com/bot)", + "id": "browser-use", + "category": "ai_agent", + "matched": true + }, + { + "userAgent": "browserbase", + "id": "browserbase", + "category": "headless_browser", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; browserbase/1.0; +http://example.com/bot)", + "id": "browserbase", + "category": "headless_browser", + "matched": true + }, + { + "userAgent": "browserless", + "id": "browserless", + "category": "headless_browser", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; browserless/1.0; +http://example.com/bot)", + "id": "browserless", + "category": "headless_browser", + "matched": true + }, + { + "userAgent": "brozzler", + "id": "brozzler", + "category": "archiver", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; brozzler/1.0; +http://example.com/bot)", + "id": "brozzler", + "category": "archiver", + "matched": true + }, + { + "userAgent": "burp", + "id": "burp", + "category": "security_scanner", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; burp/1.0; +http://example.com/bot)", + "id": "burp", + "category": "security_scanner", + "matched": true + }, + { + "userAgent": "bytespider", + "id": "bytespider", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; bytespider/1.0; +http://example.com/bot)", + "id": "bytespider", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "ccbot", + "id": "ccbot", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; ccbot/1.0; +http://example.com/bot)", + "id": "ccbot", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "censys", + "id": "censys", + "category": "security_scanner", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; censys/1.0; +http://example.com/bot)", + "id": "censys", + "category": "security_scanner", + "matched": true + }, + { + "userAgent": "chatgpt-user", + "id": "chatgpt-user", + "category": "ai_assistant", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; chatgpt-user/1.0; +http://example.com/bot)", + "id": "chatgpt-user", + "category": "ai_assistant", + "matched": true + }, + { + "userAgent": "chatgpt", + "id": "chatgpt-user", + "category": "ai_assistant", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; chatgpt/1.0; +http://example.com/bot)", + "id": "chatgpt-user", + "category": "ai_assistant", + "matched": true + }, + { + "userAgent": "claude-user", + "id": "claude-user", + "category": "ai_agent", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; claude-user/1.0; +http://example.com/bot)", + "id": "claude-user", + "category": "ai_agent", + "matched": true + }, + { + "userAgent": "claude-web", + "id": "claude-web", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; claude-web/1.0; +http://example.com/bot)", + "id": "claude-web", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "claudebot", + "id": "claudebot", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; claudebot/1.0; +http://example.com/bot)", + "id": "claudebot", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "cohere-ai", + "id": "cohere-ai", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; cohere-ai/1.0; +http://example.com/bot)", + "id": "cohere-ai", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "cohere", + "id": "cohere-ai", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; cohere/1.0; +http://example.com/bot)", + "id": "cohere-ai", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "colly", + "id": "colly", + "category": "generic_scraper", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; colly/1.0; +http://example.com/bot)", + "id": "colly", + "category": "generic_scraper", + "matched": true + }, + { + "userAgent": "commafeed", + "id": "commafeed", + "category": "feed_reader", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; commafeed/1.0; +http://example.com/bot)", + "id": "commafeed", + "category": "feed_reader", + "matched": true + }, + { + "userAgent": "contentking", + "id": "contentking", + "category": "seo_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; contentking/1.0; +http://example.com/bot)", + "id": "contentking", + "category": "seo_crawler", + "matched": true + }, + { + "userAgent": "cortana", + "id": "cortana", + "category": "ai_assistant", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; cortana/1.0; +http://example.com/bot)", + "id": "cortana", + "category": "ai_assistant", + "matched": true + }, + { + "userAgent": "crawlbase", + "id": "crawlbase", + "category": "commercial_scraper", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; crawlbase/1.0; +http://example.com/bot)", + "id": "crawlbase", + "category": "commercial_scraper", + "matched": true + }, + { + "userAgent": "datadog", + "id": "datadog-synthetics", + "category": "monitoring", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; datadog/1.0; +http://example.com/bot)", + "id": "datadog-synthetics", + "category": "monitoring", + "matched": true + }, + { + "userAgent": "deepcrawl", + "id": "deepcrawl", + "category": "seo_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; deepcrawl/1.0; +http://example.com/bot)", + "id": "deepcrawl", + "category": "seo_crawler", + "matched": true + }, + { + "userAgent": "deepseek", + "id": "deepseek", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; deepseek/1.0; +http://example.com/bot)", + "id": "deepseek", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "detectify", + "id": "detectify", + "category": "security_scanner", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; detectify/1.0; +http://example.com/bot)", + "id": "detectify", + "category": "security_scanner", + "matched": true + }, + { + "userAgent": "diffbot", + "id": "diffbot", + "category": "commercial_scraper", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; diffbot/1.0; +http://example.com/bot)", + "id": "diffbot", + "category": "commercial_scraper", + "matched": true + }, + { + "userAgent": "discordbot", + "id": "discordbot", + "category": "fetcher", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; discordbot/1.0; +http://example.com/bot)", + "id": "discordbot", + "category": "fetcher", + "matched": true + }, + { + "userAgent": "dotbot", + "id": "dotbot", + "category": "seo_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; dotbot/1.0; +http://example.com/bot)", + "id": "dotbot", + "category": "seo_crawler", + "matched": true + }, + { + "userAgent": "duckassistbot", + "id": "duckassistbot", + "category": "ai_search_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; duckassistbot/1.0; +http://example.com/bot)", + "id": "duckassistbot", + "category": "ai_search_crawler", + "matched": true + }, + { + "userAgent": "duckduckbot", + "id": "duckduckbot", + "category": "search_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; duckduckbot/1.0; +http://example.com/bot)", + "id": "duckduckbot", + "category": "search_crawler", + "matched": true + }, + { + "userAgent": "ecosia", + "id": "ecosia", + "category": "search_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; ecosia/1.0; +http://example.com/bot)", + "id": "ecosia", + "category": "search_crawler", + "matched": true + }, + { + "userAgent": "embedly", + "id": "embedly", + "category": "fetcher", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; embedly/1.0; +http://example.com/bot)", + "id": "embedly", + "category": "fetcher", + "matched": true + }, + { + "userAgent": "exa.ai", + "id": "exa", + "category": "ai_search_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; exa.ai/1.0; +http://example.com/bot)", + "id": "exa", + "category": "ai_search_crawler", + "matched": true + }, + { + "userAgent": "exabot", + "id": "exa", + "category": "ai_search_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; exabot/1.0; +http://example.com/bot)", + "id": "exa", + "category": "ai_search_crawler", + "matched": true + }, + { + "userAgent": "facebookexternalhit", + "id": "facebookexternalhit", + "category": "fetcher", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; facebookexternalhit/1.0; +http://example.com/bot)", + "id": "facebookexternalhit", + "category": "fetcher", + "matched": true + }, + { + "userAgent": "facebookbot", + "id": "facebookbot", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; facebookbot/1.0; +http://example.com/bot)", + "id": "facebookbot", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "facebot", + "id": "facebot", + "category": "fetcher", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; facebot/1.0; +http://example.com/bot)", + "id": "facebot", + "category": "fetcher", + "matched": true + }, + { + "userAgent": "faraday", + "id": "faraday", + "category": "generic_scraper", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; faraday/1.0; +http://example.com/bot)", + "id": "faraday", + "category": "generic_scraper", + "matched": true + }, + { + "userAgent": "feedbin", + "id": "feedbin", + "category": "feed_reader", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; feedbin/1.0; +http://example.com/bot)", + "id": "feedbin", + "category": "feed_reader", + "matched": true + }, + { + "userAgent": "feedfetcher", + "id": "feedfetcher-google", + "category": "feed_reader", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; feedfetcher/1.0; +http://example.com/bot)", + "id": "feedfetcher-google", + "category": "feed_reader", + "matched": true + }, + { + "userAgent": "feedly", + "id": "feedly", + "category": "feed_reader", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; feedly/1.0; +http://example.com/bot)", + "id": "feedly", + "category": "feed_reader", + "matched": true + }, + { + "userAgent": "freshrss", + "id": "freshrss", + "category": "feed_reader", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; freshrss/1.0; +http://example.com/bot)", + "id": "freshrss", + "category": "feed_reader", + "matched": true + }, + { + "userAgent": "freshping", + "id": "freshping", + "category": "monitoring", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; freshping/1.0; +http://example.com/bot)", + "id": "freshping", + "category": "monitoring", + "matched": true + }, + { + "userAgent": "friendlycrawler", + "id": "friendlycrawler", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; friendlycrawler/1.0; +http://example.com/bot)", + "id": "friendlycrawler", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "gptbot", + "id": "gptbot", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; gptbot/1.0; +http://example.com/bot)", + "id": "gptbot", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "gtmetrix", + "id": "gtmetrix", + "category": "monitoring", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; gtmetrix/1.0; +http://example.com/bot)", + "id": "gtmetrix", + "category": "monitoring", + "matched": true + }, + { + "userAgent": "gemini", + "id": "gemini", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; gemini/1.0; +http://example.com/bot)", + "id": "gemini", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "gemini-deep-research", + "id": "gemini", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; gemini-deep-research/1.0; +http://example.com/bot)", + "id": "gemini", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "gemini-user", + "id": "gemini", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; gemini-user/1.0; +http://example.com/bot)", + "id": "gemini", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "go-http-client", + "id": "go-http-client", + "category": "generic_scraper", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; go-http-client/1.0; +http://example.com/bot)", + "id": "go-http-client", + "category": "generic_scraper", + "matched": true + }, + { + "userAgent": "google-extended", + "id": "google-extended", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; google-extended/1.0; +http://example.com/bot)", + "id": "google-extended", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "google-inspectiontool", + "id": "google-inspectiontool", + "category": "search_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; google-inspectiontool/1.0; +http://example.com/bot)", + "id": "google-inspectiontool", + "category": "search_crawler", + "matched": true + }, + { + "userAgent": "googleagent-mariner", + "id": "googleagent-mariner", + "category": "ai_agent", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; googleagent-mariner/1.0; +http://example.com/bot)", + "id": "googleagent-mariner", + "category": "ai_agent", + "matched": true + }, + { + "userAgent": "mariner", + "id": "googleagent-mariner", + "category": "ai_agent", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; mariner/1.0; +http://example.com/bot)", + "id": "googleagent-mariner", + "category": "ai_agent", + "matched": true + }, + { + "userAgent": "googlebot", + "id": "googlebot", + "category": "search_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; googlebot/1.0; +http://example.com/bot)", + "id": "googlebot", + "category": "search_crawler", + "matched": true + }, + { + "userAgent": "got/", + "id": "got", + "category": "generic_scraper", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; got//1.0; +http://example.com/bot)", + "id": "got", + "category": "generic_scraper", + "matched": true + }, + { + "userAgent": "guzzlehttp", + "id": "guzzlehttp", + "category": "generic_scraper", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; guzzlehttp/1.0; +http://example.com/bot)", + "id": "guzzlehttp", + "category": "generic_scraper", + "matched": true + }, + { + "userAgent": "httpx", + "id": "httpx", + "category": "generic_scraper", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; httpx/1.0; +http://example.com/bot)", + "id": "httpx", + "category": "generic_scraper", + "matched": true + }, + { + "userAgent": "httrack", + "id": "httrack", + "category": "fetcher", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; httrack/1.0; +http://example.com/bot)", + "id": "httrack", + "category": "fetcher", + "matched": true + }, + { + "userAgent": "headlesschrome", + "id": "headlesschrome", + "category": "headless_browser", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; headlesschrome/1.0; +http://example.com/bot)", + "id": "headlesschrome", + "category": "headless_browser", + "matched": true + }, + { + "userAgent": "heritrix", + "id": "heritrix", + "category": "archiver", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; heritrix/1.0; +http://example.com/bot)", + "id": "heritrix", + "category": "archiver", + "matched": true + }, + { + "userAgent": "hetrixtools", + "id": "hetrixtools", + "category": "monitoring", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; hetrixtools/1.0; +http://example.com/bot)", + "id": "hetrixtools", + "category": "monitoring", + "matched": true + }, + { + "userAgent": "isscyberriskcrawler", + "id": "isscyberriskcrawler", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; isscyberriskcrawler/1.0; +http://example.com/bot)", + "id": "isscyberriskcrawler", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "iboubot", + "id": "iboubot", + "category": "search_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; iboubot/1.0; +http://example.com/bot)", + "id": "iboubot", + "category": "search_crawler", + "matched": true + }, + { + "userAgent": "iframely", + "id": "iframely", + "category": "fetcher", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; iframely/1.0; +http://example.com/bot)", + "id": "iframely", + "category": "fetcher", + "matched": true + }, + { + "userAgent": "import.io", + "id": "import-io", + "category": "commercial_scraper", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; import.io/1.0; +http://example.com/bot)", + "id": "import-io", + "category": "commercial_scraper", + "matched": true + }, + { + "userAgent": "inoreader", + "id": "inoreader", + "category": "feed_reader", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; inoreader/1.0; +http://example.com/bot)", + "id": "inoreader", + "category": "feed_reader", + "matched": true + }, + { + "userAgent": "ia_archiver", + "id": "ia-archiver", + "category": "archiver", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; ia_archiver/1.0; +http://example.com/bot)", + "id": "ia-archiver", + "category": "archiver", + "matched": true + }, + { + "userAgent": "intruder", + "id": "intruder", + "category": "security_scanner", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; intruder/1.0; +http://example.com/bot)", + "id": "intruder", + "category": "security_scanner", + "matched": true + }, + { + "userAgent": "java/", + "id": "java", + "category": "generic_scraper", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; java//1.0; +http://example.com/bot)", + "id": "java", + "category": "generic_scraper", + "matched": true + }, + { + "userAgent": "jsoup", + "id": "jsoup", + "category": "generic_scraper", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; jsoup/1.0; +http://example.com/bot)", + "id": "jsoup", + "category": "generic_scraper", + "matched": true + }, + { + "userAgent": "kagi", + "id": "kagi", + "category": "ai_search_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; kagi/1.0; +http://example.com/bot)", + "id": "kagi", + "category": "ai_search_crawler", + "matched": true + }, + { + "userAgent": "lwp-", + "id": "lwp", + "category": "fetcher", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; lwp-/1.0; +http://example.com/bot)", + "id": "lwp", + "category": "fetcher", + "matched": true + }, + { + "userAgent": "chrome-lighthouse", + "id": "chrome-lighthouse", + "category": "monitoring", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; chrome-lighthouse/1.0; +http://example.com/bot)", + "id": "chrome-lighthouse", + "category": "monitoring", + "matched": true + }, + { + "userAgent": "google page speed", + "id": "chrome-lighthouse", + "category": "monitoring", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; google page speed/1.0; +http://example.com/bot)", + "id": "chrome-lighthouse", + "category": "monitoring", + "matched": true + }, + { + "userAgent": "linkedinbot", + "id": "linkedinbot", + "category": "fetcher", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; linkedinbot/1.0; +http://example.com/bot)", + "id": "linkedinbot", + "category": "fetcher", + "matched": true + }, + { + "userAgent": "linkupbot", + "id": "linkupbot", + "category": "ai_search_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; linkupbot/1.0; +http://example.com/bot)", + "id": "linkupbot", + "category": "ai_search_crawler", + "matched": true + }, + { + "userAgent": "mj12bot", + "id": "mj12bot", + "category": "seo_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; mj12bot/1.0; +http://example.com/bot)", + "id": "mj12bot", + "category": "seo_crawler", + "matched": true + }, + { + "userAgent": "msnbot", + "id": "msnbot", + "category": "search_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; msnbot/1.0; +http://example.com/bot)", + "id": "msnbot", + "category": "search_crawler", + "matched": true + }, + { + "userAgent": "mechanize", + "id": "mechanize", + "category": "generic_scraper", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; mechanize/1.0; +http://example.com/bot)", + "id": "mechanize", + "category": "generic_scraper", + "matched": true + }, + { + "userAgent": "meta-externalagent", + "id": "meta-externalagent", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; meta-externalagent/1.0; +http://example.com/bot)", + "id": "meta-externalagent", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "metaphor", + "id": "metaphor", + "category": "ai_search_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; metaphor/1.0; +http://example.com/bot)", + "id": "metaphor", + "category": "ai_search_crawler", + "matched": true + }, + { + "userAgent": "copilot", + "id": "copilot", + "category": "ai_assistant", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; copilot/1.0; +http://example.com/bot)", + "id": "copilot", + "category": "ai_assistant", + "matched": true + }, + { + "userAgent": "miniflux", + "id": "miniflux", + "category": "feed_reader", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; miniflux/1.0; +http://example.com/bot)", + "id": "miniflux", + "category": "feed_reader", + "matched": true + }, + { + "userAgent": "mistral", + "id": "mistral", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; mistral/1.0; +http://example.com/bot)", + "id": "mistral", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "mojeekbot", + "id": "mojeek", + "category": "search_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; mojeekbot/1.0; +http://example.com/bot)", + "id": "mojeek", + "category": "search_crawler", + "matched": true + }, + { + "userAgent": "multion", + "id": "multion", + "category": "ai_agent", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; multion/1.0; +http://example.com/bot)", + "id": "multion", + "category": "ai_agent", + "matched": true + }, + { + "userAgent": "naver", + "id": "naver", + "category": "search_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; naver/1.0; +http://example.com/bot)", + "id": "naver", + "category": "search_crawler", + "matched": true + }, + { + "userAgent": "yeti", + "id": "naver", + "category": "search_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; yeti/1.0; +http://example.com/bot)", + "id": "naver", + "category": "search_crawler", + "matched": true + }, + { + "userAgent": "neevabot", + "id": "neeva", + "category": "ai_search_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; neevabot/1.0; +http://example.com/bot)", + "id": "neeva", + "category": "ai_search_crawler", + "matched": true + }, + { + "userAgent": "nessus", + "id": "nessus", + "category": "security_scanner", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; nessus/1.0; +http://example.com/bot)", + "id": "nessus", + "category": "security_scanner", + "matched": true + }, + { + "userAgent": "netsparker", + "id": "netsparker", + "category": "security_scanner", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; netsparker/1.0; +http://example.com/bot)", + "id": "netsparker", + "category": "security_scanner", + "matched": true + }, + { + "userAgent": "newrelic", + "id": "newrelic", + "category": "monitoring", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; newrelic/1.0; +http://example.com/bot)", + "id": "newrelic", + "category": "monitoring", + "matched": true + }, + { + "userAgent": "newsblur", + "id": "newsblur", + "category": "feed_reader", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; newsblur/1.0; +http://example.com/bot)", + "id": "newsblur", + "category": "feed_reader", + "matched": true + }, + { + "userAgent": "nikto", + "id": "nikto", + "category": "security_scanner", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; nikto/1.0; +http://example.com/bot)", + "id": "nikto", + "category": "security_scanner", + "matched": true + }, + { + "userAgent": "nmap", + "id": "nmap", + "category": "security_scanner", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; nmap/1.0; +http://example.com/bot)", + "id": "nmap", + "category": "security_scanner", + "matched": true + }, + { + "userAgent": "nodeping", + "id": "nodeping", + "category": "monitoring", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; nodeping/1.0; +http://example.com/bot)", + "id": "nodeping", + "category": "monitoring", + "matched": true + }, + { + "userAgent": "nuclei", + "id": "nuclei", + "category": "security_scanner", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; nuclei/1.0; +http://example.com/bot)", + "id": "nuclei", + "category": "security_scanner", + "matched": true + }, + { + "userAgent": "oai-searchbot", + "id": "oai-searchbot", + "category": "ai_search_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; oai-searchbot/1.0; +http://example.com/bot)", + "id": "oai-searchbot", + "category": "ai_search_crawler", + "matched": true + }, + { + "userAgent": "zap/", + "id": "zap", + "category": "security_scanner", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; zap//1.0; +http://example.com/bot)", + "id": "zap", + "category": "security_scanner", + "matched": true + }, + { + "userAgent": "okhttp", + "id": "okhttp", + "category": "generic_scraper", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; okhttp/1.0; +http://example.com/bot)", + "id": "okhttp", + "category": "generic_scraper", + "matched": true + }, + { + "userAgent": "omgili", + "id": "omgili", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; omgili/1.0; +http://example.com/bot)", + "id": "omgili", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "oncrawl", + "id": "oncrawl", + "category": "seo_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; oncrawl/1.0; +http://example.com/bot)", + "id": "oncrawl", + "category": "seo_crawler", + "matched": true + }, + { + "userAgent": "operator", + "id": "operator", + "category": "ai_agent", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; operator/1.0; +http://example.com/bot)", + "id": "operator", + "category": "ai_agent", + "matched": true + }, + { + "userAgent": "oxylabs", + "id": "oxylabs", + "category": "commercial_scraper", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; oxylabs/1.0; +http://example.com/bot)", + "id": "oxylabs", + "category": "commercial_scraper", + "matched": true + }, + { + "userAgent": "php/", + "id": "php", + "category": "generic_scraper", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; php//1.0; +http://example.com/bot)", + "id": "php", + "category": "generic_scraper", + "matched": true + }, + { + "userAgent": "perplexitybot", + "id": "perplexitybot", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; perplexitybot/1.0; +http://example.com/bot)", + "id": "perplexitybot", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "phantomjs", + "id": "phantomjs", + "category": "headless_browser", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; phantomjs/1.0; +http://example.com/bot)", + "id": "phantomjs", + "category": "headless_browser", + "matched": true + }, + { + "userAgent": "phind", + "id": "phind", + "category": "ai_search_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; phind/1.0; +http://example.com/bot)", + "id": "phind", + "category": "ai_search_crawler", + "matched": true + }, + { + "userAgent": "pingdom", + "id": "pingdom", + "category": "monitoring", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; pingdom/1.0; +http://example.com/bot)", + "id": "pingdom", + "category": "monitoring", + "matched": true + }, + { + "userAgent": "pinterest", + "id": "pinterestbot", + "category": "fetcher", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; pinterest/1.0; +http://example.com/bot)", + "id": "pinterestbot", + "category": "fetcher", + "matched": true + }, + { + "userAgent": "playwright", + "id": "playwright", + "category": "headless_browser", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; playwright/1.0; +http://example.com/bot)", + "id": "playwright", + "category": "headless_browser", + "matched": true + }, + { + "userAgent": "puppeteer", + "id": "puppeteer", + "category": "headless_browser", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; puppeteer/1.0; +http://example.com/bot)", + "id": "puppeteer", + "category": "headless_browser", + "matched": true + }, + { + "userAgent": "python/", + "id": "python", + "category": "generic_scraper", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; python//1.0; +http://example.com/bot)", + "id": "python", + "category": "generic_scraper", + "matched": true + }, + { + "userAgent": "python-requests", + "id": "python-requests", + "category": "generic_scraper", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; python-requests/1.0; +http://example.com/bot)", + "id": "python-requests", + "category": "generic_scraper", + "matched": true + }, + { + "userAgent": "python-urllib", + "id": "python-urllib", + "category": "generic_scraper", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; python-urllib/1.0; +http://example.com/bot)", + "id": "python-urllib", + "category": "generic_scraper", + "matched": true + }, + { + "userAgent": "qualys", + "id": "qualys", + "category": "security_scanner", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; qualys/1.0; +http://example.com/bot)", + "id": "qualys", + "category": "security_scanner", + "matched": true + }, + { + "userAgent": "qwantify", + "id": "qwantify", + "category": "search_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; qwantify/1.0; +http://example.com/bot)", + "id": "qwantify", + "category": "search_crawler", + "matched": true + }, + { + "userAgent": "qwen", + "id": "qwen", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; qwen/1.0; +http://example.com/bot)", + "id": "qwen", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "reddit", + "id": "reddit", + "category": "fetcher", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; reddit/1.0; +http://example.com/bot)", + "id": "reddit", + "category": "fetcher", + "matched": true + }, + { + "userAgent": "reflectionbot", + "id": "reflectionbot", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; reflectionbot/1.0; +http://example.com/bot)", + "id": "reflectionbot", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "rogerbot", + "id": "rogerbot", + "category": "seo_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; rogerbot/1.0; +http://example.com/bot)", + "id": "rogerbot", + "category": "seo_crawler", + "matched": true + }, + { + "userAgent": "ruby", + "id": "ruby", + "category": "generic_scraper", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; ruby/1.0; +http://example.com/bot)", + "id": "ruby", + "category": "generic_scraper", + "matched": true + }, + { + "userAgent": "sistrix", + "id": "sistrix", + "category": "seo_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; sistrix/1.0; +http://example.com/bot)", + "id": "sistrix", + "category": "seo_crawler", + "matched": true + }, + { + "userAgent": "scrapingant", + "id": "scrapingant", + "category": "commercial_scraper", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; scrapingant/1.0; +http://example.com/bot)", + "id": "scrapingant", + "category": "commercial_scraper", + "matched": true + }, + { + "userAgent": "scrapingbee", + "id": "scrapingbee", + "category": "commercial_scraper", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; scrapingbee/1.0; +http://example.com/bot)", + "id": "scrapingbee", + "category": "commercial_scraper", + "matched": true + }, + { + "userAgent": "scrapy", + "id": "scrapy", + "category": "generic_scraper", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; scrapy/1.0; +http://example.com/bot)", + "id": "scrapy", + "category": "generic_scraper", + "matched": true + }, + { + "userAgent": "screaming frog", + "id": "screaming-frog", + "category": "seo_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; screaming frog/1.0; +http://example.com/bot)", + "id": "screaming-frog", + "category": "seo_crawler", + "matched": true + }, + { + "userAgent": "searchgpt", + "id": "searchgpt", + "category": "ai_search_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; searchgpt/1.0; +http://example.com/bot)", + "id": "searchgpt", + "category": "ai_search_crawler", + "matched": true + }, + { + "userAgent": "selenium", + "id": "selenium", + "category": "headless_browser", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; selenium/1.0; +http://example.com/bot)", + "id": "selenium", + "category": "headless_browser", + "matched": true + }, + { + "userAgent": "semrushbot", + "id": "semrushbot", + "category": "seo_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; semrushbot/1.0; +http://example.com/bot)", + "id": "semrushbot", + "category": "seo_crawler", + "matched": true + }, + { + "userAgent": "semrush", + "id": "semrushbot", + "category": "seo_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; semrush/1.0; +http://example.com/bot)", + "id": "semrushbot", + "category": "seo_crawler", + "matched": true + }, + { + "userAgent": "sentibot", + "id": "sentibot", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; sentibot/1.0; +http://example.com/bot)", + "id": "sentibot", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "serpstat", + "id": "serpstat", + "category": "seo_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; serpstat/1.0; +http://example.com/bot)", + "id": "serpstat", + "category": "seo_crawler", + "matched": true + }, + { + "userAgent": "seznambot", + "id": "seznam", + "category": "search_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; seznambot/1.0; +http://example.com/bot)", + "id": "seznam", + "category": "search_crawler", + "matched": true + }, + { + "userAgent": "shodan", + "id": "shodan", + "category": "security_scanner", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; shodan/1.0; +http://example.com/bot)", + "id": "shodan", + "category": "security_scanner", + "matched": true + }, + { + "userAgent": "siri", + "id": "siri", + "category": "ai_assistant", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; siri/1.0; +http://example.com/bot)", + "id": "siri", + "category": "ai_assistant", + "matched": true + }, + { + "userAgent": "site24x7", + "id": "site24x7", + "category": "monitoring", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; site24x7/1.0; +http://example.com/bot)", + "id": "site24x7", + "category": "monitoring", + "matched": true + }, + { + "userAgent": "sitebulb", + "id": "sitebulb", + "category": "seo_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; sitebulb/1.0; +http://example.com/bot)", + "id": "sitebulb", + "category": "seo_crawler", + "matched": true + }, + { + "userAgent": "slackbot", + "id": "slackbot", + "category": "fetcher", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; slackbot/1.0; +http://example.com/bot)", + "id": "slackbot", + "category": "fetcher", + "matched": true + }, + { + "userAgent": "sofyabot", + "id": "sofyabot", + "category": "ai_search_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; sofyabot/1.0; +http://example.com/bot)", + "id": "sofyabot", + "category": "ai_search_crawler", + "matched": true + }, + { + "userAgent": "sogou", + "id": "sogou", + "category": "search_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; sogou/1.0; +http://example.com/bot)", + "id": "sogou", + "category": "search_crawler", + "matched": true + }, + { + "userAgent": "splash", + "id": "splash", + "category": "headless_browser", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; splash/1.0; +http://example.com/bot)", + "id": "splash", + "category": "headless_browser", + "matched": true + }, + { + "userAgent": "spyfu", + "id": "spyfu", + "category": "seo_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; spyfu/1.0; +http://example.com/bot)", + "id": "spyfu", + "category": "seo_crawler", + "matched": true + }, + { + "userAgent": "stagehand", + "id": "stagehand", + "category": "ai_agent", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; stagehand/1.0; +http://example.com/bot)", + "id": "stagehand", + "category": "ai_agent", + "matched": true + }, + { + "userAgent": "statuscake", + "id": "statuscake", + "category": "monitoring", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; statuscake/1.0; +http://example.com/bot)", + "id": "statuscake", + "category": "monitoring", + "matched": true + }, + { + "userAgent": "tavily", + "id": "tavily", + "category": "ai_search_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; tavily/1.0; +http://example.com/bot)", + "id": "tavily", + "category": "ai_search_crawler", + "matched": true + }, + { + "userAgent": "telegrambot", + "id": "telegrambot", + "category": "fetcher", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; telegrambot/1.0; +http://example.com/bot)", + "id": "telegrambot", + "category": "fetcher", + "matched": true + }, + { + "userAgent": "theoldreader", + "id": "theoldreader", + "category": "feed_reader", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; theoldreader/1.0; +http://example.com/bot)", + "id": "theoldreader", + "category": "feed_reader", + "matched": true + }, + { + "userAgent": "timpibot", + "id": "timpibot", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; timpibot/1.0; +http://example.com/bot)", + "id": "timpibot", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "tumblr", + "id": "tumblr", + "category": "fetcher", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; tumblr/1.0; +http://example.com/bot)", + "id": "tumblr", + "category": "fetcher", + "matched": true + }, + { + "userAgent": "twitterbot", + "id": "twitterbot", + "category": "fetcher", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; twitterbot/1.0; +http://example.com/bot)", + "id": "twitterbot", + "category": "fetcher", + "matched": true + }, + { + "userAgent": "undici", + "id": "undici", + "category": "generic_scraper", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; undici/1.0; +http://example.com/bot)", + "id": "undici", + "category": "generic_scraper", + "matched": true + }, + { + "userAgent": "uptimerobot", + "id": "uptimerobot", + "category": "monitoring", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; uptimerobot/1.0; +http://example.com/bot)", + "id": "uptimerobot", + "category": "monitoring", + "matched": true + }, + { + "userAgent": "velenpublicwebcrawler", + "id": "velenpublicwebcrawler", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; velenpublicwebcrawler/1.0; +http://example.com/bot)", + "id": "velenpublicwebcrawler", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "wayback", + "id": "wayback", + "category": "archiver", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; wayback/1.0; +http://example.com/bot)", + "id": "wayback", + "category": "archiver", + "matched": true + }, + { + "userAgent": "webdecoybot", + "id": "webdecoybot", + "category": "monitoring", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; webdecoybot/1.0; +http://example.com/bot)", + "id": "webdecoybot", + "category": "monitoring", + "matched": true + }, + { + "userAgent": "webscrapingapi", + "id": "webscrapingapi", + "category": "commercial_scraper", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; webscrapingapi/1.0; +http://example.com/bot)", + "id": "webscrapingapi", + "category": "commercial_scraper", + "matched": true + }, + { + "userAgent": "webzio", + "id": "webzio", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; webzio/1.0; +http://example.com/bot)", + "id": "webzio", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "wget/", + "id": "wget", + "category": "fetcher", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; wget//1.0; +http://example.com/bot)", + "id": "wget", + "category": "fetcher", + "matched": true + }, + { + "userAgent": "whatsapp", + "id": "whatsapp", + "category": "fetcher", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; whatsapp/1.0; +http://example.com/bot)", + "id": "whatsapp", + "category": "fetcher", + "matched": true + }, + { + "userAgent": "slurp", + "id": "yahoo-slurp", + "category": "search_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; slurp/1.0; +http://example.com/bot)", + "id": "yahoo-slurp", + "category": "search_crawler", + "matched": true + }, + { + "userAgent": "yandexbot", + "id": "yandexbot", + "category": "search_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; yandexbot/1.0; +http://example.com/bot)", + "id": "yandexbot", + "category": "search_crawler", + "matched": true + }, + { + "userAgent": "youbot", + "id": "youbot", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; youbot/1.0; +http://example.com/bot)", + "id": "youbot", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "zyte", + "id": "zyte", + "category": "commercial_scraper", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; zyte/1.0; +http://example.com/bot)", + "id": "zyte", + "category": "commercial_scraper", + "matched": true + }, + { + "userAgent": "scrapinghub", + "id": "zyte", + "category": "commercial_scraper", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; scrapinghub/1.0; +http://example.com/bot)", + "id": "zyte", + "category": "commercial_scraper", + "matched": true + }, + { + "userAgent": "aiohttp", + "id": "aiohttp", + "category": "generic_scraper", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; aiohttp/1.0; +http://example.com/bot)", + "id": "aiohttp", + "category": "generic_scraper", + "matched": true + }, + { + "userAgent": "curl/", + "id": "curl", + "category": "fetcher", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; curl//1.0; +http://example.com/bot)", + "id": "curl", + "category": "fetcher", + "matched": true + }, + { + "userAgent": "img2dataset", + "id": "img2dataset", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; img2dataset/1.0; +http://example.com/bot)", + "id": "img2dataset", + "category": "training_crawler", + "matched": true + }, + { + "userAgent": "libwww-perl", + "id": "libwww-perl", + "category": "fetcher", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; libwww-perl/1.0; +http://example.com/bot)", + "id": "libwww-perl", + "category": "fetcher", + "matched": true + }, + { + "userAgent": "node-fetch", + "id": "node-fetch", + "category": "generic_scraper", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; node-fetch/1.0; +http://example.com/bot)", + "id": "node-fetch", + "category": "generic_scraper", + "matched": true + }, + { + "userAgent": "xai-searchbot", + "id": "xai-searchbot", + "category": "ai_search_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (compatible; xai-searchbot/1.0; +http://example.com/bot)", + "id": "xai-searchbot", + "category": "ai_search_crawler", + "matched": true + }, + { + "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36", + "matched": false + }, + { + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Mobile/15E148 Safari/604.1", + "matched": false + }, + { + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:127.0) Gecko/20100101 Firefox/127.0", + "matched": false + }, + { + "userAgent": "", + "matched": false + } +] diff --git a/tests/AgentRegistryTest.php b/tests/AgentRegistryTest.php new file mode 100644 index 0000000..8d8de60 --- /dev/null +++ b/tests/AgentRegistryTest.php @@ -0,0 +1,117 @@ += 182, 'the registry lost agents'); + $true(in_array('training_crawler', \WebDecoy\AgentRegistry::categories(), true), 'customer-facing category names'); + foreach (\WebDecoy\AgentRegistry::all() as $agent) { + $true(array_key_exists('behavior', $agent), 'agent ' . $agent['id'] . ' has no behavior key'); + } +}); + +$t('every shared parity vector matches as it does in Go', function () use ($same) { + $path = dirname(__DIR__) . '/sdk/src/registry/parity-vectors.generated.json'; + $vectors = json_decode((string) file_get_contents($path), true); + if (!is_array($vectors) || count($vectors) === 0) { + throw new \RuntimeException('no parity vectors'); + } + foreach ($vectors as $v) { + $hit = \WebDecoy\AgentRegistry::match((string) $v['userAgent']); + if (!$v['matched']) { + $same($hit, null, 'expected no match for ' . $v['userAgent']); + continue; + } + $same($hit['id'] ?? null, $v['id'], 'id for ' . $v['userAgent']); + $same($hit['category'] ?? null, $v['category'], 'category for ' . $v['userAgent']); + } +}); + +$t('a deliberately changed generated entry is caught', function () use ($same) { + // The vectors pin ids; a hand edit that renamed an agent or reordered two + // overlapping patterns would fail the parity test above. This pins the + // one ordering case that bit the Node SDK: applebot-extended must be + // taken before applebot. + $same(\WebDecoy\AgentRegistry::match('Mozilla/5.0 (compatible; Applebot-Extended/0.1)')['id'], 'applebot-extended'); + $same(\WebDecoy\AgentRegistry::match('Mozilla/5.0 (compatible; Applebot/0.1)')['id'], 'applebot'); +}); + +$t('plugin categories are a stated function of registry categories', function () use ($same) { + $list = new \WebDecoy\GoodBotList(); + $cases = [ + 'Googlebot/2.1' => \WebDecoy\GoodBotList::CATEGORY_SEARCH_ENGINE, + 'Mozilla/5.0 (compatible; Exabot/3.0)' => \WebDecoy\GoodBotList::CATEGORY_SEARCH_ENGINE, + 'GPTBot/1.2' => \WebDecoy\GoodBotList::CATEGORY_AI_CRAWLER, + 'ChatGPT-User/1.0' => \WebDecoy\GoodBotList::CATEGORY_AI_CRAWLER, + 'Claude-User/1.0' => \WebDecoy\GoodBotList::CATEGORY_AI_CRAWLER, + 'facebookexternalhit/1.1' => \WebDecoy\GoodBotList::CATEGORY_SOCIAL, + 'UptimeRobot/2.0' => \WebDecoy\GoodBotList::CATEGORY_MONITORING, + 'AhrefsBot/7.0' => \WebDecoy\GoodBotList::CATEGORY_SEO, + 'Feedly/1.0' => \WebDecoy\GoodBotList::CATEGORY_FEED, + 'ia_archiver' => \WebDecoy\GoodBotList::CATEGORY_ARCHIVE, + ]; + foreach ($cases as $ua => $want) { + $same($list->identify($ua)['category'] ?? null, $want, $ua); + } + // Not good bots: identified by the registry, but not here. + foreach (['python-requests/2.32', 'HeadlessChrome/120', 'Nikto/2.1', 'Mozilla/5.0 (compatible; Bright Data)'] as $ua) { + $same($list->identify($ua), null, $ua . ' is not a good bot'); + } +}); + +$t('every crawler the old table named is still identified', function () use ($true) { + $list = new \WebDecoy\GoodBotList(); + // The old GoodBotList patterns, minus the two W3C validators that were + // dropped (they were never allowed; see the changelog). + $old = [ + 'googlebot', 'google-inspectiontool', 'bingbot', 'msnbot', 'yandexbot', 'baiduspider', 'duckduckbot', + 'slurp', 'sogou', 'exabot', 'qwantify', 'applebot', 'gptbot', 'chatgpt-user', 'oai-searchbot', + 'claudebot', 'claude-web', 'anthropic-ai', 'perplexitybot', 'ccbot', 'cohere-ai', 'google-extended', + 'meta-externalagent', 'amazonbot', 'twitterbot', 'facebookexternalhit', 'facebot', 'linkedinbot', + 'pinterestbot', 'slackbot', 'telegrambot', 'whatsapp', 'discordbot', 'redditbot', 'pingdom', + 'uptimerobot', 'newrelicpinger', 'datadogsynthetics', 'statuscake', 'site24x7', 'gtmetrix', + 'chrome-lighthouse', 'semrushbot', 'ahrefsbot', 'mj12bot', 'dotbot', 'screaming frog', 'feedfetcher', + 'feedly', 'newsblur', 'archive.org_bot', 'ia_archiver', + ]; + foreach ($old as $ua) { + $true($list->identify($ua) !== null, $ua . ' lost its identity'); + } +}); + +$t('verification is keyed by registry id and reachable by matched pattern', function () use ($true, $same) { + $list = new \WebDecoy\GoodBotList(); + $bot = $list->identify('Mozilla/5.0 (compatible; Pinterestbot/1.0)'); + $same($bot['id'], 'pinterestbot'); + $true($list->requiresVerification($bot['id']), 'by id'); + $true($list->requiresVerification($bot['pattern']), 'by matched pattern'); + $true(!$list->requiresVerification('uptimerobot'), 'monitoring does not verify'); + $same($list->identify('GPTBot/1.2')['behavior'], 'training'); + $same($list->identify('Googlebot/2.1')['behavior'], 'search'); +}); diff --git a/tests/AiCrawlerPolicyTest.php b/tests/AiCrawlerPolicyTest.php index 6c0e571..d682b37 100644 --- a/tests/AiCrawlerPolicyTest.php +++ b/tests/AiCrawlerPolicyTest.php @@ -23,7 +23,7 @@ function get_transient($key) { return false; } if (!function_exists('set_transient')) { function set_transient($key, $value, $ttl = 0) { return true; } } -foreach (['DetectionResult', 'GoodBotList', 'SignalCollector', 'MitreMapping', 'BotDetector'] as $class) { +foreach (['DetectionResult', 'AgentRegistry', 'GoodBotList', 'SignalCollector', 'MitreMapping', 'BotDetector'] as $class) { $file = dirname(__DIR__) . '/sdk/src/' . $class . '.php'; if (is_file($file)) { require_once $file; diff --git a/webdecoy.php b/webdecoy.php index b2cda3c..bdbc889 100644 --- a/webdecoy.php +++ b/webdecoy.php @@ -69,6 +69,7 @@ function str_starts_with(string $haystack, string $needle): bool require_once $sdk_path . 'src/Exception/WebDecoyException.php'; require_once $sdk_path . 'src/Detection.php'; require_once $sdk_path . 'src/DetectionResult.php'; + require_once $sdk_path . 'src/AgentRegistry.php'; require_once $sdk_path . 'src/GoodBotList.php'; require_once $sdk_path . 'src/SignalCollector.php'; require_once $sdk_path . 'src/BotDetector.php';