What Does Your User Agent Say About You?


A user agent is a computer program representing a person, for example, a browser in a Web context.

Besides a browser, a user agent could be a bot scraping webpages, a download manager, or another app accessing the Web. Along with each request they make to the server, browsers include a self-identifying User-Agent HTTP header called a user agent (UA) string. This string often identifies the browser, its version number, and its host operating system.

Spam bots, download managers, and some browsers often send a fake UA string to announce themselves as a different client. This is known as user agent spoofing.

The user agent string can be accessed with JavaScript on the client side using the navigator.userAgent property.

A typical user agent string looks like this: "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:35.0) Gecko/20100101 Firefox/35.0".


User Agent String

Browser Data

User Agent Length

Carole Stephens
• Wednesday, 09 December, 2020
• 25 min read

HTTP's specification does not limit length of headers at all. However, web-servers do limit header size they accept, throwing 413 Entity Too Large if it exceeds.

agent user security cisco technote useragent unknown shown status tab select protocols ports following


Use a dedicated table to store only Reagents (normalize it) In your related tables, store a Foreign Key value to point back to the Sergeant auto-increment primary key field Store the actual Sergeant string in a TEXT field and care not about the length Have another UNIQUE BINARY(32) (or 64, or 128 depending on your hash length) and hash the Sergeant Also enforce a maximum length in your INSERTer to keep UA strings it under 4 KB.

Coventry CodeAngry11.6k33 gold badges4242 silver badges5050 bronze badges It looks abnormal to me but I regularly see such things in logs mostly from Windows systems.

Harry harry93111 gold badge1111 silver badges1313 bronze badges Since it's for database purposes and there is no practical limit I'd go for a Reagents Table with UserAgentId as Int and UserAgentString as NASCAR(MAX) and use a foreign key on the original table.

Assume the user agent string has no limit on its length and prepare to store such a value. In Postgres, there's a text type that accepts strings of unlimited length.

Rv: gecko version indicates the release version of Gecko (such as 17.0 “). The Chrome (or Chromium/Blink-based engines) user agent string is similar to Firefox’s.

agent user option

For compatibility, it adds strings like HTML, like Gecko and Safari. The Opera browser is also based on the Blink engine, which is why it almost looks the same, but adds “Or/”.

In this example, the user agent string is mobile Safari’s version. Making statements based on opinion; back them up with references or personal experience.

There are ways to develop your website to progressively enhance itself based on the availability of features rather than by targeting specific browsers. Using the user agent to detect the browser looks simple, but doing it well is, in fact, a very hard problem.

Also, experts, or people with another point of view, can give you ideas for working around the bug. Your site needs to use a specific Web feature that some browsers don't yet support, and you want to send those users to an older Website with fewer features but that you know will work.

This is the worst reason to use user agent detection because odds are eventually all the other browsers will catch up. The difficulty of successfully using user agent detection is worth a few disruptions to the purity of your HTML.

user illustration modification string agent log

Also, rethink your design: can you use progressive enhancement or fluid layouts to help remove the need to do this? In those rare cases where behavior differs between browsers, instead of checking the user agent string, you should instead implement a test to detect how the browser implements the API and determine how to use it from that.

Support could have been added to other browsers at any time, but this code would have continued choosing the inferior path. As the above code demonstrates, there is always a way to test browser support without user agent sniffing.

For example, in the above code snippets, using look behind in short-regexp notation (e.g. /reg/IGM) will cause a parser error in unsupported browsers. Progressive enhancement This design technique involves developing your Website in 'layers', using a bottom-up approach, starting with a simpler layer and improving the capabilities of the site in successive layers, each using more features.

Graceful degradation This is a top-down approach in which you build the best possible site using all the features you want, then tweak it to make it work on older browsers. People use user agent sniffing to detect if the users' device is touch-friendly and has a small screen, so they can optimize their website accordingly.

While user agent sniffing can sometimes detect these, not all devices are the same: some mobile devices have big screened sizes, some desktops have a small touchscreen, some people use smart TV's which are an entirely different ballgame altogether, and some people can dynamically change the width and height of their screen by flipping their tablet on its side! Rather, add in touch conveniences such as bigger, more easily clickable buttons (you can do this using CSS by increasing the font size).

spider ninja crawl executed script output menu website

Here is an example of code that increases the padding of #exampleButton to 1em on mobile devices. This effect can be easily achieved using CSS flex boxes, sometimes with floats as a partial fallback. Also try to move less relevant/important information down to the bottom and group the page's content together meaningfully.

Although it is off-topic, perhaps the following detailed example might give you insights and ideas that persuade you to forgo user agent sniffing. The boxes can be separated into multiple columns via two equally fair method.

The second method uses a Column layout and resents all the dogs to the left and all the cats to the right. Only in this particular scenario, it is appropriate to provide no fallback for the flex boxes/multi columns, resulting in a single column of very wide boxes on old browsers.

If more people visit the webpage to see the cats, then it might be a good idea to put all the cats higher in the source code than the dogs so that more people can find what they are looking for faster on smaller screens where the content collapses down to one column. Next, always make your code dynamic. The user can flip their mobile device on its side, changing the width and height of the page.

Or, there might be some weird flip-phone-like device thing in the future where flipping it out extends the screen. The simplest way to do this is to separate all the code that moves content around based on screen size to a single function that is called when the page is loaded and at each resize event thereafter.

iphone agent user change info way there mac

Also note that there is a huge difference between the media queries (max-width: 25em), not all and (min-width: 25em), and (max-width: 24.99em) : (max-width: 25em) excludes (max-width: 25em), whereas not all and (min-width: 25em) includes (max-width: 25em). One such case is using user agent sniffing as a fallback when detecting if the device has a touch screen.

Internet Explorer (on Windows) and WebKit (on iOS) are two perfect examples. However, Internet Explorer was such a special little wasp exception prior to version 9 that it was very easy to detect the browser based upon the browser-specific features available.

WebKit is a bit worse because Apple forces all the browsers on IOS to use WebKit internally, thus the user has no way to get a better more updated browser on older devices. For example, WebKit 6 has a bug whereby when the device orientation changes, the browser might not fire MediaQueryList listeners when it should.

Most browsers set the name and version in the format BrowserName/VersionNumber, with the notable exception of Internet Explorer. So to detect Safari you have to check for the Safari string and the absence of the Chrome string, Chromium often reports itself as Chrome too or Sea monkey sometimes reports itself as Firefox.

The browser version is often, but not always, put in the value part of the BrowserName/VersionNumber token in the Sergeant String. There are five major rendering engines: Trident, Gecko, Presto, Blink, and WebKit.

waf aws protect application agent matching

It is therefore important to pay attention not to trigger false-positives when detecting the rendering engine. Must containGeckoGecko/xyzWebKitAppleWebKit/pay attention, WebKit browsers add a 'like Gecko' string that may trigger false positive for Gecko if the detection is not careful. PrestoOpera/XYZ Note: Presto is no longer used in Opera browser builds >= version 15 (see 'Blink')Trident Trident/Internet Explorer put this token in the comment part of the Sergeant StringEdgeHTMLEdge/the non-Chromium Edge puts its engine version after the Edge/ token, not the application version.

Note: Edge HTML is no longer used in Edge browser builds >= version 79 (see 'Blink'). BlinkChrome/XYZ Most rendering engines put the version number in the RenderingEngine/VersionNumber token, with the notable exception of Gecko. The Operating System is given in most Sergeant strings (although not web-focused platforms like Firefox OS), but the format varies a lot.

They indicate the OS, but also often its version and information on the relying on hardware (32 or 64 bits, or Intel/PPC for Mac). Like in all cases, these strings may change in the future, one should use them only in conjunction with the detection of already released browsers.

A technological survey must be in place to adapt the script when new browser versions are coming out. The most common reason to perform user agent sniffing is to determine which type of device the browser runs on.

Never assume that a browser or a rendering engine only runs on one type of device. Never use the OS token to define if a browser is on mobile, tablet or desktop.

agent user ip failed crawls fix website deepcrawl address blocked

Internet Explorer Immobile/XYZ token in the comment. Mozilla/5.0 (compatible; MSI 9.0; Windows Phone OS 7.5; Trident/5.0; Immobile/9.0)Edge on Windows 10 Mobile/XYZ & Edge/ tokens outside the comment. Mozilla/5.0 (Windows Phone 10.0; Android 6.0.1; Xbox; Xbox One) Apple WebKit/537.36 (HTML, like Gecko) Chrome/58.0.3029.110 Mobile Safari/537.36 Edge/16.16299In summary, we recommend looking for the string “Mob” anywhere in the Sergeant to detect a mobile device. If the device is large enough that it's not marked with “Mob”, you should serve your desktop site (which, as a best practice, should support touch input anyway, as more desktop machines are appearing with touchscreens).

Most fields using product tokens also allow sub-products which form a significant part of the application to be listed, separated by white space. The tokens are typically listed by significance, however this is completely left up to software publisher.

In summary, it is not a very standardized format, and as we will see, has evolved into a fairly chaotic environment that can be only unraveled by sustained and dedicated attention to mapping and interpreting this entropy. One of the main use cases of an user agent parser is to identify and handle requests from certain types of traffic.

This is particularly useful when dealing with the wide spectrum of devices in use today, and allows you to get as fine-grained as you like with your content targeting strategy. Outside of web optimization, this has obvious applications to the advertising sector, where the device can be useful as a criterion for targeting.

Bots and crawlers have User -Agents too, and can be identified accurately by a good device detection solution. Security is the other big area where being aware of the nature of traffic hitting your services is extremely important.

agent api user scalable cloud based request shown delivers definitions parameters lookup string example above single programmableweb below

These range from search engines to link checkers, SEO tools, feed readers, scripts and other nefarious actors at large in the web landscape. Being able to distinguish between these different sources can provide significant savings in IT costs by detecting and identifying bot traffic to your site.

You would need to constantly update your regex rules as new devices, browsers and OSs are released, and then run tests to see if the solution still works well. At some point, this becomes a costly maintenance job, and, over time, a real risk that you are misdirecting or failing to detect much of your traffic. Accurately parsing User -Agents is one problem.

Device Atlas uses a Patricia train data structure to determine the properties of a device in the quickest and most efficient way. This is the reason why major companies rely on established solutions built on proven and patented technology like Device Atlas.

During the first browser war, many web servers were configured to send web pages that required advanced features, including frames, to clients that were identified as some version of Mozilla only. Other browsers were considered to be older products such as Mosaic, Cello, or Samba, and would be sent a bare-bones HTML document.

Automated agents are expected to follow rules in a special file called robots.txt “. The popularity of various Web browser products has varied throughout the Web's history, and this has influenced the design of websites in such a way that websites are sometimes designed to work well only with particular browsers, rather than according to uniform standards by the World Wide Web Consortium (W3C) or the Internet Engineering Task Force (IETF).

agent api user scalable cloud based request example parameters delivers portion lookups defines bulk string below shows programmableweb array parameter

Websites often include code to detect browser version to adjust the page design sent according to the user agent string received. Thus, various browsers have a feature to cloak or spoof their identification to force certain server-side content.

For example, the Android browser identifies itself as Safari (among other things) in order to aid compatibility. User agent sniffing is the practice of websites showing different or adjusted content when viewed with certain user agents.

An example of this is Microsoft Exchange Server 2003's Outlook Web Access feature. When viewed with Internet Explorer 6 or newer, more functionality is displayed compared to the same page in any other browsers.

Web browsers created in the United States, such as Netscape Navigator and Internet Explorer, previously used the letters U, I, and N to specify the encryption strength in the user agent string. Until 1996, when the United States government disallowed encryption with keys longer than 40 bits to be exported, vendors shipped various browser versions with different encryption strengths.

^ a b RFC 3261, SIP: Session Initiation Protocol, IETF, The Internet Society (2002) ^ RFC 7231, Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content, IETF, The Internet Society (June 2014) ^ Net news Article Format. Browser Versions Carry 10.5 Bits of Identifying Information on Average “, Electronic Frontier Foundation, 27 January 2010.

wireshark agent user hex strings pcap malware final navigate editor way

I've been rejected until I come back with Netscape” ^ “Android Browser Reports Itself as Apple Safari”. ^ User Agent String explained: Android WebKit Browser”.

Mozilla/5.0 (Linux; U; Android 2.2; ends; HTC_DesireHD_A9191 Build/FRF91) Apple WebKit/533.1 (HTML, like Gecko) Version/4.0 Mobile Safari/533.1 ^ Emberton, Stephen. ^ “Chrome Phasing out Support for User Agent ".

You can think of it as a way to describe and display data that would make sense in spreadsheet software. Imagine running your finger across a row (horizontal) to see a single person and relevant information about them.

Or up and down a column (vertical) to get a sense of the variety or pattern of data on that point. One thing we didn’t do in the very basic example above is semantically indicated that the first row was the header of the table.

That entire first row contains no data, it is simply the titles of columns. When you use , there must be no that is a direct child of


reporting bundle agent user extrahop screenshots

Notice that we also wrapped all the rows of data in here. Like , best for semantically indicating these are not data rows but ancillary information.

Back before HTML5, the element was required to be after and before ! You might think it would be the last thing before the end of

, but wasn’t the case.

It can be used, for example, to repeat the header in the case of a visually very tall/long table where it may be easier to see the column titles at the bottom than the top. The individual cells of a table are always one of two elements:

is wrapped within a automatically.

But when rendered, both of those columns get wrapped in a col group, so the CSS selector will select the first one. If you use a head, the whole table will be wrapped in that until it find a body, then it will auto-close the head if you don’t, and wrap the rest in body (also optional to close).


Just makes me feel better knowing parent elements are also along for the ride and won’t get freaky. This is primarily useful in responsive design where the traditional table layout makes sense on large screens but needs significant shifts to make sense on smaller screens.

We already talked about the problems with using tables for layout and accessibility. But assuming table is being correctly used for tabular data, there are still quite a few accessibility concerns.

We’re using the body in the selector because it’s unlikely you’d want to stripe header and footer rows. If you need to support browsers that don’t understand :nth-child() (pretty damn old) you could use jQuery to do it.

One possibility is to use the

element, which does allow us to set styles for cells that appear in that column. It’s weird to wrap your head around, because the cells that are affected by aren’t actually descendants of it.

A table with four columns in each row would have four

elements: You’re probably better off setting a class name on each individual table cell element that happens to match that column position in the row.


I used jQuery to make it all 12 lines of code (the raw JavaScript was getting pretty exhausting). It’s the same concept, it’s just much easier to make element collections, and find and select by indexes in jQuery.

The most modern way of handling fixed headers is position: sticky; Here’s an article on that. I’m honestly not quite sure the recommended way to use it with tables though.

That kinda makes sense because you can’t absolutely position table innards. Since tables are so repetitive and verbose, Emmett is perfect for them.

JavaScript provides some very specific methods for dealing with tables through the HTMLTableElement API. You can use it to create tables with JavaScript, access sub-elements, and change properties in very specific ways.

It would be handy to be able to click those headers and sort the table by the data inside. For instance, numerical order, alternating between ascending and descending, for the ID’s and alphabetical for the email addresses.

This is such a common and generic need, that there is actually specification ready for it. Just put the sortable attribute on the table and it will automatically do it as long as you follow a couple of rules laid out in the spec.

Update June 2109: Removed link, it no longer mentions sortable. At the time of this writing, I don’t know of any browsers supporting table sorting natively.

Other Articles You Might Be Interested In

01: Python Requests Header User Agent
02: Python User Agent Library
03: Python Wget User Agent
04: Free Download User Agent Switcher For Firefox
05: Tablet User Agent String
06: Android Chrome Change User Agent
07: Android Edge Change User Agent
08: Android Firefox User Agent String
09: Googlebot User Agent String
10: Google Chrome Change User Agent String
1 -
2 -
3 -
4 -
5 -
6 -
7 -
8 -
or .

Notice the slight extra gap between the first row and the rest. That is caused by the default border-spacing being applied to the and pushing them apart a bit extra.

There are two important attributes that can go on any table cell element (

or ): col span and row span. You’ll have to do a bit of mental math when you start working with connected cells.


Row span is similar, it’s just a little harder and more of a mental leap, because columns aren’t grouped like rows are. If a table element has a row span attribute, it spans across two rows vertically.

Often these attributes are used in really simple ways like connecting a few related table headers: It behaves like a block-level element (e.g.

) in that if you put one table after another, each will break down onto its own line.

But the actual width of the table is only as wide as it needs to be. If the amount of text (if put on one line) would be wider than the container, it will wrap.

However, if text is told to not wrap (i.e. white-space: no wrap;) the table is happy to bust out of the container and go wider. It’s just no more important than the vertical column of headers so it feels weird to group that top row alone.

It’s a good time to take a break and discuss the when of tables. Perhaps you’ve heard the generic advice: tables are for tabular data (see the first sentence of this blog post).

sessions unique radio spent agent listening average ip user

Here are some: a plan/pricing/features comparison, bowling scores, an internal grid of employee data, financial data, a calendar, the nutrition facts information panel, a logic puzzle solver, etc. At a glance at how tables work may make them seem ideal for layout.

Easy to control, extremely logical, predictable, and not-at-all fragile. As we covered, table elements semantically describe tabular data.

Screen readers read tables from top to bottom, left to right. That means the order of how your site is presented is dictated by the table structure, which is dictated by visual choices not accessibility choices.

Not to mention a screen reader may even announce the start of tabular data which would be worse than useless. A table would dictate that table comes first in the source order, which while also being bad for accessibility, is likely bad for SEO as well, potentially valuing your ancillary content above primary content.

If you really need the layout abilities of a table but want to use semantic tags, see the next section. As I write this in the latter half of 2013, tables have become far less prevalent and even appealing as a layout choice.

chrome agent user random

We’re seeing a lot more use of fixed and absolute positioning which you cannot do inside a table. Rarely do you see modern websites touch tables for layout.

The landscape of what renders emails is super wide. It is everything we deal with on the web, plus the world of native apps on both mobile and desktop on operating systems new and ancient.

You can do some progressive enhancement for emails, but the layout itself is still generally regarded as being safest done in tables. That is substantiated by the fact that the major email sending services still all offer templates as tables.

If that layout style solves a problem and has no negative order implications, use it. It otherwise behaves just like a

, so, no need to replicate it in CSS.

Remember we talked about how weird table elements widths are above. I’ve never been a huge fan of that title as it suggests that using this table style layout is the right way and any other layout technique you use is the wrong way.

agent user scalable api cloud based delivers discerned demo string url screenshot brand area parts type into programmableweb

Just be acutely aware that no matter what kind of elements you used to create a table-based layout, it is still subjects to the same problems (largely source order dependency). UPDATE: I’m told this was removed from spec because of lack of implementations.

But this attribute isn’t supported either, so no big loss.Chaffee abovebgcolorUse background property instead abbr“consider starting the cell content by an independent abbreviated content itself or use the abbreviated content as the cell content and use the long content as the description of the cell by putting it in the title attribute” axisUse the scope attribute insteadborderUse border property insteadcellpaddingUsing padding property insteadcellspacingUse border-spacing property insteadframeUse border property instead rules User border property insteadsummaryUse

element insteadwidthUse width property instead There is an implied vertical stacking of table elements, just like there is in any HTML parent > descendant scenario. CSS PropertyPossible valuesWhat it doesvertical-alignbaselinesubsupertext-toptext-bottommiddletopbottom% length Aligns the content inside a cell.

The styles applied to these types of elements will “win”, in order of “strength”: cell, row, row group, column, column group, table.border-spacing length If border-collapse is separate, you can specify how far cells should be spaced out from each other. And speaking of that, padding is the modern version of the cell padding attribute.width length Width works on table cells just about how you would think it does, except when there is some kind of conflict.

That’s assuming white-space or elements like an image don’t come into play. The width of the table and its cells depends on the content inside.

Cells in subsequent rows do not affect column widths, which can speed up rendering. If content in subsequent cells can’t fit, the overflow property determines what happens. This list isn’t exhaustive.


If you can think of more CSS weirdness with tables, share in the comments below. I inspected each element in Chrome Dev Tools too, which is now on Blink, and it’s still the same.

For example, in Firefox (here’s 3.6’s UA Stylesheet, but this is true in v23 too) table cells have this: That’s what CSS resets (and related projects) are all about: removing the differences.

I’m a fan of border-collapse: collapse because spacing between cells is usually way awkward, but, the default in every browser I know of is border-collapse: separate; so isn’t in need of normalization. Table cell elements are in need of normalization (e.g. Firefox padding difference) but that isn’t there.


element doesn’t need to be closed in certain circumstances: “The end tag may be omitted, if it is immediately followed by a or element or if there are no more data in its parent element.” The missing closing tag is the same story: “The end tag may be omitted if the element is immediately followed by a element, or if the parent table group (, or ) element doesn’t have any more content.” One thing to notice is the