JavaScript Tutorial

Navigator Object in JavaScript: Complete Guide with Examples

Master the JavaScript Navigator object — user agent, browser language, online status, geolocation, platform, clipboard, media devices, and real-world examples with best practices.

Welcome back! 👋 In the previous lesson, you mastered the history object. Now let's explore the navigator object — the window into everything the browser knows about itself and the user's device!

The navigator object gives you access to browser type, language settings, online/offline status, the user's physical location, clipboard access, installed plugins, and much more. You'll use it to build adaptive, device-aware experiences — detecting when users go offline, requesting their location, or accessing their camera and microphone.

Let's master it completely!


What is the Navigator Object?

The navigator object (window.navigator) provides information about the browser and the device it's running on. Unlike window (which controls the browser window) or document (which controls the page content), navigator tells you who and what is accessing your page.

console.log(window.navigator); // Navigator object
console.log(navigator);        // Same — window is implicit

console.log(navigator.userAgent);  // Browser identification string
console.log(navigator.language);   // User's preferred language
console.log(navigator.onLine);     // Is the user online?

Browser Information

navigator.userAgent — Browser Identity String

The most well-known navigator property — a string that identifies the browser, its version, and the OS.

console.log(navigator.userAgent);
// Chrome on Windows:
// "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36"

// Chrome on Android:
// "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Mobile Safari/537.36"

// Safari on iPhone:
// "Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1"

Detect Browser Type

function getBrowserInfo() {
  let ua = navigator.userAgent;

  let browser =
    ua.includes("Edg")    ? "Microsoft Edge" :
    ua.includes("OPR")    ? "Opera"          :
    ua.includes("Chrome") ? "Chrome"         :
    ua.includes("Safari") ? "Safari"         :
    ua.includes("Firefox") ? "Firefox"       :
    "Unknown Browser";

  let isDesktop = !ua.includes("Mobile") && !ua.includes("Android");
  let device    = isDesktop ? "Desktop" : "Mobile";

  return { browser, device, ua };
}

let info = getBrowserInfo();
console.log(`Browser: ${info.browser}`);
console.log(`Device:  ${info.device}`);

navigator.vendor — Browser Vendor

console.log(navigator.vendor);
// Chrome: "Google Inc."
// Safari: "Apple Computer, Inc."
// Firefox: "" (empty string)

navigator.appVersion — Browser Version Info

console.log(navigator.appVersion);
// "5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36..."

Language and Locale

navigator.language — User's Primary Language

console.log(navigator.language);
// "en-IN" (English, India)
// "hi-IN" (Hindi, India)
// "en-US" (English, US)
// "fr-FR" (French, France)

navigator.languages — All Preferred Languages (in order)

console.log(navigator.languages);
// ["en-IN", "en-GB", "en", "hi"] — user's language preferences in order

Practical — Detect and Apply Language

function getUserLocale() {
  let lang = navigator.language || navigator.languages[0] || "en";
  let [language, region] = lang.split("-");

  return {
    full:     lang,
    language: language.toLowerCase(),
    region:   region?.toUpperCase() ?? "US",
    isRTL:    ["ar", "he", "fa", "ur"].includes(language.toLowerCase()),
  };
}

let locale = getUserLocale();
console.log(`Language: ${locale.language}`);
console.log(`Region:   ${locale.region}`);
console.log(`RTL:      ${locale.isRTL}`);

// Use locale for formatting
let amount = 1234567.89;
console.log(amount.toLocaleString(locale.full, {
  style: "currency",
  currency: locale.region === "IN" ? "INR" : "USD",
}));
// e.g. "₹12,34,567.89" for en-IN

Online / Offline Status

navigator.onLine — Is the User Online?

console.log(navigator.onLine); // true or false

Listen for Online/Offline Events

window.addEventListener("online", () => {
  console.log("🟢 Back online!");
  // Sync pending data, retry failed requests
});

window.addEventListener("offline", () => {
  console.log("🔴 Gone offline!");
  // Show offline banner, queue requests
});

Practical — Offline-Aware App

class ConnectionManager {
  constructor() {
    this.isOnline  = navigator.onLine;
    this.queue     = []; // Pending requests when offline
    this.listeners = [];

    window.addEventListener("online",  () => this.handleOnline());
    window.addEventListener("offline", () => this.handleOffline());
  }

  handleOnline() {
    this.isOnline = true;
    console.log("🟢 Connection restored");
    this.notify("online");
    this.flushQueue();
  }

  handleOffline() {
    this.isOnline = false;
    console.log("🔴 Connection lost");
    this.notify("offline");
  }

  notify(status) {
    this.listeners.forEach(fn => fn(status));
  }

  onChange(fn) {
    this.listeners.push(fn);
  }

  enqueue(request) {
    if (this.isOnline) {
      return request(); // Execute immediately
    }
    this.queue.push(request);
    console.log(`📋 Queued (${this.queue.length} pending)`);
  }

  flushQueue() {
    console.log(`🔄 Flushing ${this.queue.length} queued requests`);
    while (this.queue.length) {
      this.queue.shift()();
    }
  }
}

let conn = new ConnectionManager();

conn.onChange(status => {
  let banner = document.getElementById("offlineBanner");
  if (banner) {
    banner.style.display = status === "offline" ? "block" : "none";
  }
});

// Queue a request when offline
conn.enqueue(() => console.log("📤 Sending form data..."));

Geolocation

The Geolocation API lets you request the user's physical location — with their explicit permission.

navigator.geolocation.getCurrentPosition() — One-Time Location

function getLocation() {
  if (!navigator.geolocation) {
    console.log("❌ Geolocation not supported by this browser");
    return;
  }

  navigator.geolocation.getCurrentPosition(
    // Success callback
    (position) => {
      let { latitude, longitude, accuracy, altitude, speed } = position.coords;
      let timestamp = new Date(position.timestamp);

      console.log(`📍 Latitude:  ${latitude}`);
      console.log(`📍 Longitude: ${longitude}`);
      console.log(`📍 Accuracy:  ${accuracy} meters`);
      console.log(`⏱️  Time:      ${timestamp.toLocaleTimeString()}`);
    },
    // Error callback
    (error) => {
      let messages = {
        1: "Permission denied — user blocked location access",
        2: "Position unavailable — location service failed",
        3: "Timeout — took too long to get location",
      };
      console.log(`❌ Error: ${messages[error.code]}`);
    },
    // Options
    {
      enableHighAccuracy: true,  // Use GPS if available
      timeout:            10000, // Give up after 10 seconds
      maximumAge:         0,     // Don't use cached position
    }
  );
}

getLocation();

navigator.geolocation.watchPosition() — Track Live Location

let watchId = navigator.geolocation.watchPosition(
  (position) => {
    let { latitude, longitude } = position.coords;
    console.log(`📍 Updated position: ${latitude}, ${longitude}`);
    // Update map marker in real time
  },
  (error) => {
    console.error("Location error:", error.message);
  },
  { enableHighAccuracy: true, timeout: 5000 }
);

// Stop tracking
function stopTracking() {
  navigator.geolocation.clearWatch(watchId);
  console.log("🛑 Location tracking stopped");
}

// Stop after 30 seconds
setTimeout(stopTracking, 30000);

Practical — Nearest Store Finder

function findNearestStore(userLat, userLon, stores) {
  function distanceKm(lat1, lon1, lat2, lon2) {
    let R    = 6371; // Earth radius in km
    let dLat = (lat2 - lat1) * Math.PI / 180;
    let dLon = (lon2 - lon1) * Math.PI / 180;
    let a    =
      Math.sin(dLat/2) ** 2 +
      Math.cos(lat1 * Math.PI / 180) *
      Math.cos(lat2 * Math.PI / 180) *
      Math.sin(dLon/2) ** 2;
    return R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
  }

  return stores
    .map(store => ({
      ...store,
      distanceKm: distanceKm(userLat, userLon, store.lat, store.lon).toFixed(2),
    }))
    .sort((a, b) => a.distanceKm - b.distanceKm);
}

let stores = [
  { name: "Andheri Store",  lat: 19.1197, lon: 72.8464 },
  { name: "Bandra Store",   lat: 19.0596, lon: 72.8295 },
  { name: "Dadar Store",    lat: 19.0178, lon: 72.8478 },
];

navigator.geolocation.getCurrentPosition(({ coords }) => {
  let sorted = findNearestStore(coords.latitude, coords.longitude, stores);
  console.log("🏪 Nearest stores:");
  sorted.forEach(s => console.log(`  ${s.name}: ${s.distanceKm} km away`));
});

Platform and Device Info

navigator.platform — Operating System

console.log(navigator.platform);
// "Win32"      — Windows
// "MacIntel"   — macOS
// "Linux x86_64" — Linux
// "iPhone"     — iOS
// "Android"    — Android (some browsers)

navigator.hardwareConcurrency — CPU Cores

console.log(navigator.hardwareConcurrency);
// e.g. 8 — number of logical CPU cores
// Useful for deciding how many Web Workers to spawn

navigator.deviceMemory — Device RAM (GB)

console.log(navigator.deviceMemory);
// e.g. 8 — 8GB RAM
// Values are rounded: 0.25, 0.5, 1, 2, 4, 8
// Useful for adapting to low-memory devices

navigator.maxTouchPoints — Is it a Touch Device?

console.log(navigator.maxTouchPoints);
// 0 — no touch support (desktop)
// 1 — basic touch (some laptops)
// 5+ — multi-touch (phones, tablets)

let isTouchDevice = navigator.maxTouchPoints > 0;
console.log(`Touch device: ${isTouchDevice}`);

Practical — Device Capability Detector

function detectDeviceCapabilities() {
  return {
    cores:       navigator.hardwareConcurrency   ?? "unknown",
    ram:         navigator.deviceMemory          ?? "unknown",
    touch:       navigator.maxTouchPoints > 0,
    touchPoints: navigator.maxTouchPoints,
    online:      navigator.onLine,
    language:    navigator.language,
    platform:    navigator.platform,
  };
}

let caps = detectDeviceCapabilities();

console.log("=== 📱 Device Capabilities ===");
for (let [key, val] of Object.entries(caps)) {
  console.log(`  ${key.padEnd(12)}: ${val}`);
}

// Adapt experience based on capabilities
if (caps.ram <= 2) {
  console.log("⚠️ Low RAM device — using lightweight mode");
}
if (caps.touch) {
  console.log("📱 Touch device — enabling swipe gestures");
}
if (!caps.online) {
  console.log("🔴 Offline — enabling offline mode");
}

Clipboard API

navigator.clipboard.writeText() — Copy to Clipboard

async function copyToClipboard(text) {
  try {
    await navigator.clipboard.writeText(text);
    console.log(`✅ Copied: "${text}"`);
  } catch (err) {
    console.error("❌ Copy failed:", err.message);
  }
}

copyToClipboard("Hello, World!");

// Common pattern — copy button
document.getElementById("copyBtn")?.addEventListener("click", async () => {
  let code = document.getElementById("codeBlock").textContent;
  await copyToClipboard(code);

  let btn = document.getElementById("copyBtn");
  btn.textContent = "✅ Copied!";
  setTimeout(() => btn.textContent = "Copy", 2000);
});

navigator.clipboard.readText() — Paste from Clipboard

async function pasteFromClipboard() {
  try {
    let text = await navigator.clipboard.readText();
    console.log(`📋 Pasted: "${text}"`);
    return text;
  } catch (err) {
    console.error("❌ Paste failed:", err.message);
    return null;
  }
}

Share API

navigator.share() — Native Share Dialog

Opens the device's native share sheet — works on mobile browsers.

async function shareContent(data) {
  if (!navigator.share) {
    console.log("❌ Web Share API not supported");
    // Fallback: copy URL to clipboard
    await navigator.clipboard.writeText(data.url ?? window.location.href);
    return;
  }

  try {
    await navigator.share({
      title: data.title ?? document.title,
      text:  data.text  ?? "",
      url:   data.url   ?? window.location.href,
    });
    console.log("✅ Shared successfully");
  } catch (err) {
    if (err.name !== "AbortError") {
      console.error("Share failed:", err.message);
    }
  }
}

document.getElementById("shareBtn")?.addEventListener("click", () => {
  shareContent({
    title: "Learn JavaScript — DOM & BOM",
    text:  "Check out this amazing JavaScript tutorial!",
    url:   window.location.href,
  });
});

Real-World Examples

Example 1: Complete Device Info Panel

function buildDeviceReport() {
  let ua     = navigator.userAgent;
  let isMobile = /Android|iPhone|iPad|iPod|BlackBerry|IEMobile/i.test(ua);

  let report = {
    "Browser":     getBrowserName(ua),
    "Platform":    navigator.platform,
    "Language":    navigator.language,
    "Online":      navigator.onLine ? "✅ Yes" : "❌ No",
    "Touch":       navigator.maxTouchPoints > 0 ? `✅ Yes (${navigator.maxTouchPoints} points)` : "❌ No",
    "CPU Cores":   navigator.hardwareConcurrency ?? "Unknown",
    "RAM":         navigator.deviceMemory ? `${navigator.deviceMemory} GB` : "Unknown",
    "Device Type": isMobile ? "📱 Mobile" : "🖥️ Desktop",
    "Cookies":     navigator.cookieEnabled ? "✅ Enabled" : "❌ Disabled",
  };

  console.log("=== 📊 Device Report ===");
  for (let [key, val] of Object.entries(report)) {
    console.log(`  ${key.padEnd(14)}: ${val}`);
  }

  return report;
}

function getBrowserName(ua) {
  if (ua.includes("Edg"))     return "Microsoft Edge";
  if (ua.includes("OPR"))     return "Opera";
  if (ua.includes("Chrome"))  return "Chrome";
  if (ua.includes("Safari"))  return "Safari";
  if (ua.includes("Firefox")) return "Firefox";
  return "Unknown";
}

buildDeviceReport();

Example 2: Location-Based Greeting

async function personalizeGreeting() {
  let greeting = "Hello";
  let langMap  = {
    "hi": "नमस्ते",
    "fr": "Bonjour",
    "de": "Hallo",
    "es": "Hola",
    "ja": "こんにちは",
    "ar": "مرحبا",
  };

  let lang     = navigator.language.split("-")[0].toLowerCase();
  greeting     = langMap[lang] ?? "Hello";

  let timeStr  = new Date().toLocaleTimeString(navigator.language);
  let dateStr  = new Date().toLocaleDateString(navigator.language, {
    weekday: "long", day: "numeric", month: "long",
  });

  console.log(`${greeting}! 👋`);
  console.log(`📅 ${dateStr}`);
  console.log(`⏰ ${timeStr}`);
  console.log(`🌐 Your language: ${navigator.language}`);
  console.log(`🔗 Status: ${navigator.onLine ? "Online" : "Offline"}`);
}

personalizeGreeting();

Example 3: Progressive Feature Detection

function checkFeatureSupport() {
  let features = {
    geolocation: !!navigator.geolocation,
    clipboard:   !!navigator.clipboard,
    share:       !!navigator.share,
    bluetooth:   !!navigator.bluetooth,
    usb:         !!navigator.usb,
    vibration:   !!navigator.vibrate,
    notifications: "Notification" in window,
    serviceWorker: "serviceWorker" in navigator,
    webRTC:       !!window.RTCPeerConnection,
    localStorage:  (() => {
      try { localStorage.setItem("t", "1"); localStorage.removeItem("t"); return true; }
      catch { return false; }
    })(),
  };

  console.log("=== 🔍 Feature Support ===");
  for (let [feature, supported] of Object.entries(features)) {
    console.log(`  ${feature.padEnd(18)}: ${supported ? "✅ Supported" : "❌ Not supported"}`);
  }

  return features;
}

let features = checkFeatureSupport();

// Conditionally enable features
if (features.geolocation) {
  document.getElementById("locationBtn")?.removeAttribute("disabled");
}

if (!features.serviceWorker) {
  console.log("⚠️ No service worker — offline mode unavailable");
}

Common Mistakes

Mistake 1: Relying on userAgent for Feature Detection

// ❌ userAgent sniffing is fragile — browsers lie, strings change!
if (navigator.userAgent.includes("Chrome")) {
  enableChromeFeature(); // May break with Chrome updates ❌
}

// ✅ Use feature detection instead — check if the API exists
if ("clipboard" in navigator) {
  enableClipboardFeature(); // Works regardless of browser ✅
}

if (navigator.geolocation) {
  enableLocationFeature(); // Safe check ✅
}

Mistake 2: Not Handling Geolocation Permission Denial

// ❌ No error handling — crashes when user denies permission
navigator.geolocation.getCurrentPosition(pos => {
  showMap(pos.coords);
});

// ✅ Always handle all error cases
navigator.geolocation.getCurrentPosition(
  pos => showMap(pos.coords),
  err => {
    if (err.code === 1) console.log("Permission denied — show manual input");
    if (err.code === 2) console.log("Position unavailable — try again");
    if (err.code === 3) console.log("Timeout — check connection");
    showManualLocationInput(); // Fallback ✅
  }
);

Mistake 3: Assuming navigator.onLine Means Full Connectivity

// ⚠️ navigator.onLine only means a network interface is connected
// It does NOT mean the internet is actually reachable!

if (navigator.onLine) {
  fetchData(); // Could still fail if wifi has no internet! ⚠️
}

// ✅ Always handle fetch errors too — even when "online"
if (navigator.onLine) {
  try {
    let data = await fetch("/api/data");
    return await data.json();
  } catch (err) {
    console.log("Fetch failed despite being 'online':", err.message);
    return fallbackData;
  }
}

Mistake 4: Not Checking Clipboard API Support

// ❌ Clipboard API requires HTTPS and user permission — not always available
await navigator.clipboard.writeText(text); // Throws on HTTP! ❌

// ✅ Always check support and handle errors
async function safeCopy(text) {
  if (!navigator.clipboard) {
    // Fallback for older browsers
    let el = document.createElement("textarea");
    el.value = text;
    document.body.appendChild(el);
    el.select();
    document.execCommand("copy");
    document.body.removeChild(el);
    return;
  }

  try {
    await navigator.clipboard.writeText(text);
    console.log("✅ Copied!");
  } catch (err) {
    console.error("❌ Copy failed:", err.message);
  }
}

Navigator Properties Cheat Sheet

Property / MethodWhat it does
navigator.userAgentBrowser identification string
navigator.languageUser's primary language (e.g. "en-IN")
navigator.languagesArray of preferred languages
navigator.onLinetrue if online, false if offline
navigator.platformOS/platform string
navigator.vendorBrowser vendor name
navigator.hardwareConcurrencyNumber of logical CPU cores
navigator.deviceMemoryDevice RAM in GB (rounded)
navigator.maxTouchPointsMax simultaneous touch points
navigator.cookieEnabledAre cookies enabled?
navigator.geolocationGeolocation API object
geolocation.getCurrentPosition()Get user's location once
geolocation.watchPosition()Track location continuously
geolocation.clearWatch(id)Stop tracking location
navigator.clipboard.writeText()Copy text to clipboard
navigator.clipboard.readText()Paste text from clipboard
navigator.share()Open native share dialog
"serviceWorker" in navigatorCheck service worker support

Key Takeaways

Congratulations! 🎉 You now fully understand the navigator object and all the browser and device information it exposes.

navigator.userAgent — identifies the browser. Use for information only — not for feature detection.

navigator.language / navigator.languages — user's locale. Use for formatting dates, numbers, and currency correctly.

navigator.onLine — quick online check. Always handle fetch errors too — onLine doesn't guarantee internet.

GeolocationgetCurrentPosition() for one-time, watchPosition() for live tracking. Always handle permission denial gracefully.

Device infohardwareConcurrency, deviceMemory, maxTouchPoints for adaptive experiences.

Clipboardclipboard.writeText() / readText() — requires HTTPS and user permission. Always fall back gracefully.

navigator.share() — native share sheet on mobile. Check support before calling.

Feature detection over UA sniffing — always check "feature" in navigator rather than parsing the user agent string.


Best Practices

  1. ✅ Use feature detection ("geolocation" in navigator) — never UA sniffing for feature support
  2. ✅ Always handle geolocation permission denial — show a manual input fallback
  3. ✅ Don't trust navigator.onLine alone — always catch fetch errors too
  4. ✅ The Clipboard API requires HTTPS — always check support and have a fallback
  5. ✅ Use navigator.language for locale-aware formatting with toLocaleString()
  6. ✅ Use navigator.deviceMemory and hardwareConcurrency to adapt for low-end devices
  7. ✅ Check navigator.share before calling — it's only available on mobile browsers
  8. ✅ Always clearWatch() when you no longer need live location — saves battery

What's Next?

Great work! 🎉 You now know how to read everything the browser knows about itself and the user's device.

Next up, let's look at the user's screen:

Screen Object — screen width, height, available space, color depth, pixel ratio, and how to use them to build responsive, display-aware experiences!

Let's keep going! 💪