1 # useragent - high performance user agent parser for Node.js
3 Useragent originated as port of [browserscope.org][browserscope]'s user agent
4 parser project also known as ua-parser. Useragent allows you to parse user agent
5 string with high accuracy by using hand tuned dedicated regular expressions for
6 browser matching. This database is needed to ensure that every browser is
7 correctly parsed as every browser vendor implements it's own user agent schema.
8 This is why regular user agent parsers have major issues because they will
9 most likely parse out the wrong browser name or confuse the render engine version
10 with the actual version of the browser.
14 ### Build status [![BuildStatus](https://secure.travis-ci.org/3rd-Eden/useragent.png?branch=master)](http://travis-ci.org/3rd-Eden/useragent)
20 The module has been developed with a benchmark driven approach. It has a
21 pre-compiled library that contains all the Regular Expressions and uses deferred
22 or on demand parsing for Operating System and device information. All this
23 engineering effort has been worth it as [this benchmark shows][benchmark]:
26 Starting the benchmark, parsing 62 useragent strings per run
28 Executed benchmark against node module: "useragent"
29 Count (61), Cycles (5), Elapsed (5.559), Hz (1141.3739447904327)
31 Executed benchmark against node module: "useragent_parser"
32 Count (29), Cycles (3), Elapsed (5.448), Hz (545.6817291171243)
34 Executed benchmark against node module: "useragent-parser"
35 Count (16), Cycles (4), Elapsed (5.48), Hz (304.5373431830105)
37 Executed benchmark against node module: "ua-parser"
38 Count (54), Cycles (3), Elapsed (5.512), Hz (1018.7561434659247)
40 Module: "useragent" is the user agent fastest parser.
47 Installation is done using the Node Package Manager (NPM). If you don't have
48 NPM installed on your system you can download it from
52 npm install useragent --save
55 The `--save` flag tells NPM to automatically add it to your `package.json` file.
62 Include the `useragent` parser in you node.js application:
65 var useragent = require('useragent');
68 The `useragent` library allows you do use the automatically installed RegExp
69 library or you can fetch it live from the remote servers. So if you are
70 paranoid and always want your RegExp library to be up to date to match with
71 agent the widest range of `useragent` strings you can do:
74 var useragent = require('useragent');
78 This will async load the database from the server and compile it to a proper
79 JavaScript supported format. If it fails to compile or load it from the remote
80 location it will just fall back silently to the shipped version. If you want to
81 use this feature you need to add `yamlparser` and `request` to your package.json
84 npm install yamlparser --save
85 npm install request --save
88 #### useragent.parse(useragent string[, js useragent]);
90 This is the actual user agent parser, this is where all the magic is happening.
91 The function accepts 2 arguments, both should be a `string`. The first argument
92 should the user agent string that is known on the server from the
93 `req.headers.useragent` header. The other argument is optional and should be
94 the user agent string that you see in the browser, this can be send from the
95 browser using a xhr request or something like this. This allows you detect if
96 the user is browsing the web using the `Chrome Frame` extension.
98 The parser returns a Agent instance, this allows you to output user agent
99 information in different predefined formats. See the Agent section for more
103 var agent = useragent.parse(req.headers['user-agent']);
105 // example for parsing both the useragent header and a optional js useragent
106 var agent2 = useragent.parse(req.headers['user-agent'], req.query.jsuseragent);
109 The parse method returns a `Agent` instance which contains all details about the
110 user agent. See the Agent section of the API documentation for the available
113 #### useragent.lookup(useragent string[, js useragent]);
115 This provides the same functionality as above, but it caches the user agent
116 string and it's parsed result in memory to provide faster lookups in the
117 future. This can be handy if you expect to parse a lot of user agent strings.
119 It uses the same arguments as the `useragent.parse` method and returns exactly
120 the same result, but it's just cached.
123 var agent = useragent.lookup(req.headers['user-agent']);
126 And this is a serious performance improvement as shown in this benchmark:
129 Executed benchmark against method: "useragent.parse"
130 Count (49), Cycles (3), Elapsed (5.534), Hz (947.6844321931629)
132 Executed benchmark against method: "useragent.lookup"
133 Count (11758), Cycles (3), Elapsed (5.395), Hz (229352.03831239208)
136 #### useragent.fromJSON(obj);
138 Transforms the JSON representation of a `Agent` instance back in to a working
142 var agent = useragent.parse(req.headers['user-agent'])
143 , another = useragent.fromJSON(JSON.stringify(agent));
145 console.log(agent == another);
148 #### useragent.is(useragent string).browsername;
150 This api provides you with a quick and dirty browser lookup. The underlying
151 code is usually found on client side scripts so it's not the same quality as
152 our `useragent.parse` method but it might be needed for legacy reasons.
154 `useragent.is` returns a object with potential matched browser names
157 useragent.is(req.headers['user-agent']).firefox // true
158 useragent.is(req.headers['user-agent']).safari // false
159 var ua = useragent.is(req.headers['user-agent'])
178 ### Agents, OperatingSystem and Device instances
180 Most of the methods mentioned above return a Agent instance. The Agent exposes
181 the parsed out information from the user agent strings. This allows us to
182 extend the agent with more methods that do not necessarily need to be in the
183 core agent instance, allowing us to expose a plugin interface for third party
184 developers and at the same time create a uniform interface for all versioning.
186 The Agent has the following property
188 - `family` The browser family, or browser name, it defaults to Other.
189 - `major` The major version number of the family, it defaults to 0.
190 - `minor` The minor version number of the family, it defaults to 0.
191 - `patch` The patch version number of the family, it defaults to 0.
193 In addition to the properties mentioned above, it also has 2 special properties,
196 - `os` OperatingSystem instance
197 - `device` Device instance
199 When you access those 2 properties the agent will do on demand parsing of the
200 Operating System or/and Device information.
202 The OperatingSystem has the same properties as the Agent, for the Device we
203 don't have any versioning information available, so only the `family` property is
204 set there. If we cannot find the family, they will default to `Other`.
206 The following methods are available:
208 #### Agent.toAgent();
210 Returns the family and version number concatinated in a nice human readable
214 var agent = useragent.parse(req.headers['user-agent']);
215 agent.toAgent(); // 'Chrome 15.0.874'
218 #### Agent.toString();
220 Returns the results of the `Agent.toAgent()` but also adds the parsed operating
221 system to the string in a human readable format.
224 var agent = useragent.parse(req.headers['user-agent']);
225 agent.toString(); // 'Chrome 15.0.874 / Mac OS X 10.8.1'
227 // as it's a to string method you can also concat it with another string
228 'your useragent is ' + agent;
229 // 'your useragent is Chrome 15.0.874 / Mac OS X 10.8.1'
231 #### Agent.toVersion();
233 Returns the version of the browser in a human readable string.
236 var agent = useragent.parse(req.headers['user-agent']);
237 agent.toVersion(); // '15.0.874'
242 Generates a JSON representation of the Agent. By using the `toJSON` method we
243 automatically allow it to be stringified when supplying as to the
244 `JSON.stringify` method.
247 var agent = useragent.parse(req.headers['user-agent']);
248 agent.toJSON(); // returns an object
250 JSON.stringify(agent);
253 #### OperatingSystem.toString();
255 Generates a stringified version of operating system;
258 var agent = useragent.parse(req.headers['user-agent']);
259 agent.os.toString(); // 'Mac OSX 10.8.1'
262 #### OperatingSystem.toVersion();
264 Generates a stringified version of operating system's version;
267 var agent = useragent.parse(req.headers['user-agent']);
268 agent.os.toVersion(); // '10.8.1'
271 #### OperatingSystem.toJSON();
273 Generates a JSON representation of the OperatingSystem. By using the `toJSON`
274 method we automatically allow it to be stringified when supplying as to the
275 `JSON.stringify` method.
278 var agent = useragent.parse(req.headers['user-agent']);
279 agent.os.toJSON(); // returns an object
281 JSON.stringify(agent.os);
284 #### Device.toString();
286 Generates a stringified version of device;
289 var agent = useragent.parse(req.headers['user-agent']);
290 agent.device.toString(); // 'Asus A100'
293 #### Device.toVersion();
295 Generates a stringified version of device's version;
298 var agent = useragent.parse(req.headers['user-agent']);
299 agent.device.toVersion(); // '' , no version found but could also be '0.0.0'
302 #### Device.toJSON();
304 Generates a JSON representation of the Device. By using the `toJSON` method we
305 automatically allow it to be stringified when supplying as to the
306 `JSON.stringify` method.
309 var agent = useragent.parse(req.headers['user-agent']);
310 agent.device.toJSON(); // returns an object
312 JSON.stringify(agent.device);
315 ### Adding more features to the useragent
317 As I wanted to keep the core of the user agent parser as clean and fast as
318 possible I decided to move some of the initially planned features to a new
321 These extensions to the Agent prototype can be loaded by requiring the
322 `useragent/features` file:
325 var useragent = require('useragent');
326 require('useragent/features');
329 The initial release introduces 1 new method, satisfies, which allows you to see
330 if the version number of the browser satisfies a certain range. It uses the
331 semver library to do all the range calculations but here is a small summary of
332 the supported range styles:
334 * `>1.2.3` Greater than a specific version.
335 * `<1.2.3` Less than.
336 * `1.2.3 - 2.3.4` := `>=1.2.3 <=2.3.4`.
337 * `~1.2.3` := `>=1.2.3 <1.3.0`.
338 * `~1.2` := `>=1.2.0 <2.0.0`.
339 * `~1` := `>=1.0.0 <2.0.0`.
340 * `1.2.x` := `>=1.2.0 <1.3.0`.
341 * `1.x` := `>=1.0.0 <2.0.0`.
343 As it requires the `semver` module to function you need to install it
347 npm install semver --save
350 #### Agent.satisfies('range style here');
352 Check if the agent matches the supplied range.
355 var agent = useragent.parse(req.headers['user-agent']);
356 agent.satisfies('15.x || >=19.5.0 || 25.0.0 - 17.2.3'); // true
357 agent.satisfies('>16.12.0'); // false
363 For small changes between version please review the [changelog][changelog].
365 #### Upgrading from 1.10 to 2.0.0
367 - `useragent.fromAgent` has been removed.
368 - `agent.toJSON` now returns an Object, use `JSON.stringify(agent)` for the old
370 - `agent.os` is now an `OperatingSystem` instance with version numbers. If you
371 still a string only representation do `agent.os.toString()`.
372 - `semver` has been removed from the dependencies, so if you are using the
373 `require('useragent/features')` you need to add it to your own dependencies
375 #### Upgrading from 0.1.2 to 1.0.0
377 - `useragent.browser(ua)` has been renamed to `useragent.is(ua)`.
378 - `useragent.parser(ua, jsua)` has been renamed to `useragent.parse(ua, jsua)`.
379 - `result.pretty()` has been renamed to `result.toAgent()`.
380 - `result.V1` has been renamed to `result.major`.
381 - `result.V2` has been renamed to `result.minor`.
382 - `result.V3` has been renamed to `result.patch`.
383 - `result.prettyOS()` has been removed.
384 - `result.match` has been removed.
392 [browserscope]: http://www.browserscope.org/
393 [benchmark]: /3rd-Eden/useragent/blob/master/benchmark/run.js
394 [changelog]: /3rd-Eden/useragent/blob/master/CHANGELOG.md
395 [npm]: http://npmjs.org