Navigator Interface: Accessing the User-Agent With JavaScript
I’ve been working on a video-streaming application that requires some information about the user agent (read: browser). I was pleasantly surprised to find that each thread of research led me back to the same place: the Navigator Interface.
The Navigator Interface gives developers access to a wide range of functionality — including causing the device to vibrate (navigator.vibrate()
). I wanted to share some of the interesting things the Navigator Interface can tell us about our users (with their permission, of course).
Geolocation
Do you need to know the (approximate) geographic location of your users? You can use the Navigator Interface to request their location:
navigator.geolocation.getCurrentPosition(loc => console.log(loc))
If you copy and paste this code into your browser’s console, the browser will notify you that the website is trying to access your location. Should you allow it, a Geolocation
object will appear in your console.
Inside that object, you’ll see a latitude, longitude and accuracy value. The accuracy value is like a margin of error; it is a radius in meters that draws a circle around the given coordinates. Your user could be anywhere within that circle.
The location services available to your user depend on the machine they’re using to access your application. Typically, laptops and desktops do not have GPS capabilities, so the browser will use one of two methods to locate the user: location based on available Wifi networks or IP-based location.
If you want to be sure the browser is using the best possible method for geolocation, you can pass an options argument to the .getCurrentPosition()
method:
const options = { enableHighAccuracy: true }
navigator.geolocation.getCurrentPosition(success, error, options)
(The first two arguments are callback functions handling successful attempts to access geolocation and unsuccessful attempts, respectively.)
Media Devices
Media devices are any hardware devices that provide media input. Generally, these will be cameras and microphones. Requesting access to these devices works in a similar way to accessing geolocation; although, this method is asynchronous:
const constraints = { video: true, audio: true }
let mediaStream
navigator.mediaDevices.getUserMedia(constraints)
.then(stream => mediaStream = stream)
Here, we’re requesting access to all video and audio devices connected to the browser. Again, if you copy and paste this code into your browser, you’ll be asked to grant permission for the site to use your camera and microphone. Once granted, type mediaStream
into the console and you should see a MediaStream
object with some properties and a lot of different methods.
If you want to know more about your user’s camera(s), you can ask the MediaStream
object for an array of video devices:
const videoArray = mediaStream.getVideoTracks()
const video = videoArray[0]
I only have one camera connected to my laptop, so I’m just taking the first item of this array. This item is a MediaStreamTrack
object with a label
property that provides the name of the camera. This object has methods of its own that allow us to dig deeper into the device’s attributes:
video.getSettings()
video.getCapabilities()
The .getSettings()
method returns an object containing the camera’s set aspectRatio
, frameRate
and its height
and width
in pixels — which together comprise the resolution. The .getCapabilities()
method provides an object with the same properties, but each property points to an object with a max
and min
value.
With this information, you can prohibit users from streaming with subpar video quality. Or, you could iterate through a user’s devices and suggest the best device to use for streaming based on its capabilities.
These are just some of the interesting things you can do with the Navigator Interface. You can also view what plugins the browser is using, the user’s preferred language and even what type of connection the client is using to connect to the network and an onchange
event to respond to changes in that connection.
If you’re curious to learn more about the Navigator Interface, I encourage you to check out the MDN documentation. Note: a good amount of the features listed in the documentation are either experimental or not supported across all browsers. Be sure to check browser support for any Navigator-related task you want to use in your application.
And, because your application’s access to this information depends on the user granting permission, always include error handling at every step.