惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Google DeepMind News
Google DeepMind News
C
CERT Recently Published Vulnerability Notes
C
Cisco Blogs
Cloudbric
Cloudbric
The Last Watchdog
The Last Watchdog
L
LINUX DO - 热门话题
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Application and Cybersecurity Blog
Application and Cybersecurity Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Security Archives - TechRepublic
Security Archives - TechRepublic
TaoSecurity Blog
TaoSecurity Blog
V2EX - 技术
V2EX - 技术
H
Heimdal Security Blog
S
Security Affairs
L
Lohrmann on Cybersecurity
Hacker News - Newest:
Hacker News - Newest: "LLM"
Simon Willison's Weblog
Simon Willison's Weblog
WordPress大学
WordPress大学
小众软件
小众软件
Security Latest
Security Latest
AWS News Blog
AWS News Blog
Apple Machine Learning Research
Apple Machine Learning Research
GbyAI
GbyAI
Engineering at Meta
Engineering at Meta
阮一峰的网络日志
阮一峰的网络日志
罗磊的独立博客
F
Full Disclosure
S
Schneier on Security
L
LangChain Blog
MyScale Blog
MyScale Blog
Know Your Adversary
Know Your Adversary
P
Privacy International News Feed
Google Online Security Blog
Google Online Security Blog
Scott Helme
Scott Helme
Stack Overflow Blog
Stack Overflow Blog
爱范儿
爱范儿
A
Arctic Wolf
Martin Fowler
Martin Fowler
B
Blog RSS Feed
大猫的无限游戏
大猫的无限游戏
博客园 - 三生石上(FineUI控件)
The Register - Security
The Register - Security
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
博客园_首页
Latest news
Latest news
F
Fortinet All Blogs
G
GRAHAM CLULEY
T
The Exploit Database - CXSecurity.com
Hacker News: Ask HN
Hacker News: Ask HN

Echo JS

Desktop apps Introducing mermaid-lint: Stop Shipping Broken Diagrams How We Cut Slow Responses by 80% Migrating to Next.js App Router The quiet problem with unnecessary async - Matt Smith GitHub - ant-design/ant-design-cli: Ant Design on your command line. Query component knowledge, analyze project usage, and guide migrations — fully offline. Uncovering the Magic Behind Playwright React Performance Isn’t About useMemo — It’s About Render Boundaries T2 No Escape Hatches · Prickles GitHub - auto-agent-protocol/auto-agent-protocol: Automotive Agent Protocol GitHub - coactionjs/coaction: Zustand-style state management with built-in render tracking and cached computed state GitHub - williamtroup/Rattribute.js: ❓ A lightweight JavaScript library for automatically changing HTML element attributes based on responsive screen sizes. GitHub - williamtroup/Rink.js: 🔗 A JavaScript library for generating responsive HTML link targets. SVAR Kanban: Interactive Task Board Component for Svelte, React, and Vue Performance Cost of Popular 3rd Party Scripts date-light - Tiny date utilities for JavaScript When React Hooks Stop Scaling: Moving Complex State to Zustand - Oren Farhi GitHub - jskits/loggerjs: A faster, more powerful isomorphic logger Out Loud — Free AI Text to Speech Pocket DB — Embedded single-file NoSQL for Node.js billboard.js 4.0 release: Canvas rendering mode, 94.3% faster! GitHub - thegruber/linkpeek: Secure TypeScript link preview and URL metadata extractor for Open Graph, Twitter Cards, JSON-LD, Node/Bun/Deno/edge. GitHub - evoluteur/healing-frequencies: Play the healing frequencies of various sets of tuning forks: Solfeggio, Organs, Mineral nutrients, Ohm, Chakras, Cosmic octave, Otto, DNA nucleotides... or custom. Animated sine waves - 27 lines of pure JavaScript Framework | Neutralinojs GitHub - AllThingsSmitty/typescript-tips-everyone-should-know: ✅ A curated collection of practical TypeScript patterns that improve safety, readability, maintainability, and developer experience. 🧠 Heat.js : JavaScript Heat Map GitHub - iDev-Games/State-JS: State.js is a CSS‑reactive framework that makes UI state and updates flow through CSS instead of JavaScript logic. GitHub - yankouskia/gameplate: :video_game: Boilerplate for creating game with WebGL & Redux :game_die: GitHub - yankouskia/is-incognito-mode: Identify whether browser is in incognito mode 👀
GitHub - yankouskia/get-browser: 💻 Lightweight tool to identify the browser (mobile+desktop detection)📱
2026-07-09 · via Echo JS

get-browser — lightweight, SSR-safe browser detection

Tiny, typed, SSR-safe browser detection.
One call. One canonical answer. ~1.4 kB min+gzip. Zero dependencies.

npm size CI types MIT

📚 Docs site · 🧪 Playground · 🍳 Recipes · ↗️ v1 → v2


import { detect, getEngine, getOS, isMobile, browsers, engines, oses } from 'get-browser';

if (detect() === browsers.SAFARI && isMobile()) {
  applyMobileSafariFix();
}

if (getEngine() === engines.WEBKIT) applyWebkitScrollFix(); // also catches Chrome-iOS
const shortcut = getOS() === oses.MACOS ? '⌘ K' : 'Ctrl K';

That's the whole pitch. Three canonical questions, three strict unions:

  • detect()'chrome' | 'edge' | 'firefox' | 'safari' | 'opera' | 'ie' | 'android' | 'unknown'who.
  • getEngine()'blink' | 'gecko' | 'webkit' | 'trident' | 'presto' | 'edgehtml' | 'unknown'what renders it (correct on iOS).
  • getOS()'macos' | 'windows' | 'linux' | 'ios' | 'android' | 'chromeos' | 'unknown'where it runs.

A handful of tree-shakeable predicates do the boolean versions.

Install

pnpm add get-browser    # or npm / yarn / bun

No bundler? Drop in the UMD bundle:

<script src="https://unpkg.com/get-browser/dist/umd/get-browser.global.js"></script>
<script>
  if (GetBrowser.isMobile()) document.body.classList.add('is-mobile');
</script>

Why you'd use this

  • 🪶 Tiny — ~1.4 kB min+gzip, zero dependencies, tree-shakeable.
  • 🧠 Typeddetect() returns the Browser union, never string. Exhaustive switches compile.
  • 🏗️ SSR-safe — every detector takes { userAgent }. Works in Node, Next.js, Remix, Astro, Workers, Deno.
  • 🎯 Honest — it answers who, not what. For capability checks use @supports / matchMedia.

Tip

Want to see it in action without installing anything? Open the Playground — paste any user-agent and watch every predicate light up.

Usage

Switch on the browser
import { detect, browsers } from 'get-browser';

switch (detect()) {
  case browsers.CHROME:  loadChromeShim();          break;
  case browsers.SAFARI:  patchSafariScrollBug();    break;
  case browsers.FIREFOX: enableFirefoxOnlyFeature(); break;
  case browsers.UNKNOWN: /* bot or new browser */    break;
}
Booleans — tree-shakes to ~400 bytes per predicate
import { isMobile, isChrome, isSafari } from 'get-browser';

if (isMobile() && !isChrome()) showNonChromeMobileBanner();
if (isSafari() && isMobile()) applyMobileSafariFix();
Server-side — Next.js, Remix, Workers, Deno
// Next.js Edge route — runs on Cloudflare too
export const runtime = 'edge';

import { detect, getOS } from 'get-browser';

export function GET(req: Request) {
  const userAgent = req.headers.get('user-agent') ?? '';
  return Response.json({
    browser: detect({ userAgent }),
    // Prefer Sec-CH-UA-Platform — Chrome's UA Reduction is hollowing
    // out the legacy UA string. Get-browser reads either.
    os: getOS({
      userAgent,
      clientHints: { platform: req.headers.get('sec-ch-ua-platform') ?? undefined },
    }),
  });
}

The library never touches window at import time. Pass an explicit UA and detection becomes a pure function — perfect for tests and SSR. Full framework cookbook in the SSR guide.

Cross-platform UI — shortcuts, downloads, deep links
import { getOS, oses } from 'get-browser';

const os = getOS();

const shortcut    = os === oses.MACOS ? '⌘ K' : 'Ctrl K';
const downloadUrl = os === oses.WINDOWS ? '/dl/app.exe'
                  : os === oses.MACOS   ? '/dl/app.dmg'
                  : os === oses.LINUX   ? '/dl/app.deb'
                  : '/dl/';
const storeUrl    = os === oses.IOS     ? 'https://apps.apple.com/…'
                  : os === oses.ANDROID ? 'https://play.google.com/…'
                  : '/install';
In-app browsers — Instagram, Facebook, TikTok, X, LinkedIn, …
import { isInAppBrowser } from 'get-browser';

// OAuth providers (Google, Apple, Microsoft) block sign-in inside
// most in-app browsers. Bounce to the system browser first.
if (isInAppBrowser()) {
  showOpenInBrowserBanner({
    message: 'Tap ⋯ → "Open in browser" to continue with Google sign-in.',
  });
}

Catches Facebook (FBAN/FBAV/FB_IAB), Instagram, X/Twitter, LinkedIn, TikTok, Snapchat, WeChat, Line, Telegram, Pinterest. Stable token-based matching — version-agnostic.

Rendering engine — correct on iOS, where everything is WebKit
import { detect, getEngine, engines } from 'get-browser';

// One check covers Safari + Chrome-iOS + Firefox-iOS + Edge-iOS.
if (getEngine() === engines.WEBKIT) applyWebkitScrollFix();

// Honest analytics: "who" and "what renders it" are different questions.
analytics.track('page_view', { browser: detect(), engine: getEngine() });

getEngine() reads the engine from the UA, so Chrome-on-iOS reports 'webkit' (what actually paints the page) — not 'blink'. A hand-rolled browser → engine lookup gets that wrong.

API

A small surface — every export pulls its weight.

detect(opts?) Returns one of the browsers values
getEngine(opts?) Returns one of the engines values
getOS(opts?) Returns one of the oses values
isChrome / isEdge / isFirefox / isSafari (opts?) => boolean
isOpera / isIE / isAndroid / isMobile (opts?) => boolean
isInAppBrowser (opts?) => booleantrue inside Instagram, Facebook, TikTok, X, LinkedIn, …
browsers, oses, engines Frozen enums: { CHROME: 'chrome', ... }, { MACOS: 'macos', ... }, { WEBKIT: 'webkit', ... }
Browser, OS, Engine, DetectOptions, ClientHints Type-only exports

opts is { userAgent?: string; vendor?: string; clientHints?: { platform?: string } } — pass userAgent for SSR or tests, pass clientHints.platform (the Sec-CH-UA-Platform header) for the most reliable OS read.

Full API reference →

How it stacks up

Bundle (min+gz) get-browser detect-browser bowser ua-parser-js
🏆 ~1.4 kB ~2 kB ~7 kB ~10 kB

Pick ua-parser-js if you need version numbers or device info. Pick get-browser if you just need the single, lowercase, typed answer to which browser is this? — see the full comparison.

What it detects

Chrome Edge Firefox Safari Opera Safari iOS Android IE

Chrome, Edge (legacy & Chromium), Firefox, Safari (desktop, iOS, iPadOS), Opera (Presto & OPR), Internet Explorer 6-11, Android WebView — including iOS variants (CriOS, FxiOS, EdgiOS) and mobile / tablet user-agents. Coverage details: browser support.

Requirements

  • Node ≥ 20 (active LTS — 20, 22, 24)
  • TypeScript ≥ 5.0 if you use types
  • Browsers — evergreen. UMD bundle is ES2018.

Documentation

The full docs are built with Docusaurus and deployed to GitHub Pages:

📚 Docs 🔌 API 🧪 Playground 🍳 Recipes 🏗️ SSR 🔄 Migration

Run the docs locally:

pnpm install
pnpm run build              # build the library first
pnpm run website:install
pnpm run website:dev        # http://localhost:3000

Contributing & license

PRs welcome — see CONTRIBUTING.md. For security issues, see SECURITY.md (please don't open public issues for vulnerabilities).

MIT © yankouskia and contributors.