Files
explore/nextjs/utils/checkRealBrowser.ts
2025-08-21 13:26:00 +02:00

81 lines
2.3 KiB
TypeScript

import type { GetServerSidePropsContext } from 'next';
const GENERIC_BOT_MARKERS = [
'bot',
'spider',
'crawler',
'httpclient',
'headlesschrome',
'phantomjs',
'puppeteer',
'playwright',
'node-fetch',
'axios',
'curl',
'wget',
'python-requests',
'go-http-client',
'libwww-perl',
'okhttp',
'postman',
'insomnia',
];
function toLower(input: string | null | undefined): string {
return (input || '').toLowerCase();
}
function isGenericBotUA(userAgent: string): boolean {
const ua = toLower(userAgent);
return GENERIC_BOT_MARKERS.some((m) => ua.includes(m));
}
function hasBrowserHeuristics(req: GetServerSidePropsContext['req']): boolean {
const acceptLanguage = req.headers['accept-language'];
const secChUa = req.headers['sec-ch-ua'];
const secFetchSite = req.headers['sec-fetch-site'];
const secFetchMode = req.headers['sec-fetch-mode'];
const upgradeInsecure = req.headers['upgrade-insecure-requests'];
const hasLang = Boolean(acceptLanguage);
const hasSecHeaders = Boolean(secChUa || secFetchSite || secFetchMode || upgradeInsecure);
return hasLang && hasSecHeaders;
}
export function isLikelyHumanBrowser(req: GetServerSidePropsContext['req']): boolean {
const userAgent = req.headers['user-agent'];
if (!userAgent) return false;
if (isGenericBotUA(userAgent)) return false;
if (!hasBrowserHeuristics(req)) return false;
// Inclusive check for common engines + brands across desktop and mobile
const hasEngineToken = /applewebkit|gecko/i.test(userAgent);
const hasKnownBrowserBrand = /chrome|safari|firefox|crios|fxios|edg|opr|samsungbrowser|vivaldi|whale|duckduckgo/i.test(userAgent);
return hasEngineToken && hasKnownBrowserBrand;
}
export function isKnownBotRequest(req: GetServerSidePropsContext['req']): boolean {
const ua = toLower(req.headers['user-agent']);
if (!ua) return false;
// Social preview bots
if (ua.includes('twitter')) return true;
if (ua.includes('facebook')) return true;
if (ua.includes('telegram')) return true;
if (ua.includes('slack')) return true;
// Search engine bots
if (ua.includes('googlebot')) return true;
if (ua.includes('bingbot')) return true;
if (ua.includes('yahoo')) return true;
if (ua.includes('duckduck')) return true;
// Generic markers
if (isGenericBotUA(ua)) return true;
return false;
}