Skip to main content

Viewer location

createGlobe(canvas, { showViewer: true });

That pins the person looking at your page. No permission prompt, no network call, no API key, and it resolves instantly.

Loading globe…

How it works​

Intl.DateTimeFormat().resolvedOptions().timeZone is available in every modern browser, requires no permission, and costs nothing. The package ships the IANA time-zone table: 312 zones and 237 aliases and maps the reported zone to its published coordinate.

const found = globe.locateViewer();
// {
// lat: 23.29, lon: 82.52,
// timeZone: "Asia/Kolkata", country: "IN",
// source: "timezone", accuracy: "region",
// accuracyMeters: 2242000
// }

:::note Legacy zone names are load-bearing Chrome commonly reports Asia/Calcutta, not Asia/Kolkata. Alias resolution is why this works for a large share of real users rather than silently failing. :::

It is a region, not a pinpoint​

A time zone narrows someone to its area, and the tz database publishes one representative city per zone. Asia/Kolkata covers all of India, so a naive pin would sit confidently on Kolkata even for someone in Ahmedabad, 1,600 km away.

Two things prevent that:

Anchoring. For countries wider than 8°, the pin uses the country centroid instead of the zone's city, which roughly halves the average error. Smaller countries keep their real city: London stays London.

An uncertainty circle. The pin is surrounded by a dashed circle sized to the actual radius, so the graphic says somewhere in here rather than exactly here.

showViewer: {
anchor: "auto", // "country" | "timezone" to force it
accuracyCircle: true, // false to hide it
}

Asking for precision​

const found = await globe.locateViewer({ precise: true });
globe.setViewerLocation(found);

This requests the browser's high-accuracy provider and reports the device's own accuracyMeters, so you can tell a 20 m GPS fix from a 40 km Wi-Fi one. If the visitor declines, it resolves to the time-zone estimate and never rejects.

PromptNetworkAlways worksTypical radius
Time zone (default)NoNoYesCountry-sized
Locale fallbackNoNoYesCountry-sized
precise, GPSYesNoOnly if allowed5-50 m
precise, Wi-Fi/IPYesYes (by the browser)Only if allowed1-50 km

:::caution On a desktop, "precise" often is not A laptop with no GPS falls back to network positioning, which frequently lands on your ISP's city. The reported accuracyMeters is the only way to tell: show it, or size a circle with it, rather than implying a street address. :::

Options​

showViewer: {
emoji: "📍",
label: "You",
color: "#f97316",
live: true, // pulsing ring
anchor: "auto",
accuracyCircle: true,
accuracyColor: "#22c55e",
flyTo: true, // centre on them once located
ping: true, // fire a ping at their position
precise: false, // ask for GPS on construction
onLocate: (location) => track(location.country),
}

The pin lives outside the markers array, so setMarkers() never wipes it.

Standalone helpers​

Useful without a globe at all:

import { locateViewer, timeZoneLocation, countryLocation, placeLocation } from "canvas-globe";

locateViewer(); // the full result
timeZoneLocation("Asia/Calcutta"); // → resolves the alias
countryLocation("IN");
placeLocation("New York");

Privacy​

Nothing leaves the device. The time zone is read from the local Intl API and matched against a bundled table. There is no request, no third party, and nothing to disclose in a cookie banner: though if you send the result to your own analytics, that is your call to document.

Talk to a real person

Live human support. Choose what you need help with.