Whenever you ask for a page on the web, your request has a lot of data attached to it. One part of your request (the “user-agent” string) describes your software environment—usually your operating system and your browser’s name and version number. Like many things on the web, this data is a convention, not a law. You are free to modify it however you want. This practice is known as user-agent spoofing.
If you’re ready to give it a try yourself (and you have Google Chrome), you can find the extension (and installation instructions) here. If you’re a developer interested in modifying headers from a Chrome extension, read on!
Update II (1/24/12) It looks like Chrome 17 will ship with support for modifying the User-Agent string. (Click here for the Chromium issue and here for more info on the feature.) This renders the dedicated user-agent switching extension obsolete, but the approach outlined here may still be relevant in the context of a larger extension. Also remember the WebRequest API has many applications beyond this simple use-case!
Update I (1/3/12) In Chrome 17, the WebRequest API will lose its “experimental” designation and change slightly. This article, originally published in August 2011, has been updated to reflect these changes. For the more diff-minded developer, I’ve updated the example project with a single commit which documents the specific changes.
”permissions”: [ “webRequest” ]
…although in our specific case, we’ll need some additional permissions: one for “blocking” all requests until we’ve completely processed them, and another for our extension to operate on all URLs. That means our manifest file will actually look more like this:
"permissions": [ "webRequest", “webRequestBlocking”, “<all_urls>” ]
I’ll be focusing on the “onBeforeSendHeaders” event for now. Behaviors like request blocking and redirecting can be achieved with other event handlers, but those will have to wait for another post.
You can bind your own listener to this event in your extension’s background page. Here is an example binding which outlines the necessary steps:
…that should be enough to get you up and running.
If you’re anything like me, after reading the documentation and the above example, you still have some questions. I’ll do my best to answer them:
What are the contents of
requestHeaders? The API documentation gives hints at what it doesn’t contain, but my experience has been varied. Here’s a printout of what I’ve seen, although I’ve received confirmation from Chrome developers that the contents are variable:
How do I detach a listener? Although currently undocumented,
chrome.webRequest.onBeforeSendHeaders.removeListener() seems to work. It may be safer (for now) to begin your listener function by checking an externally-scoped
listenerIsActive flag which you can set/unset from outside the function.
How can I use requestFilter to control which requests the listener responds to? The requestFilter parameter optionally lets you filter by tab ID and window ID. You can also specify a URL pattern to filter by–the pattern schema is documented here.
Hopefully, this has been a useful introduction to Chrome’s WebRequest API. As you have seen, it is now possible to spoof the user-agent string from an extension. The API seems to be stabilizing in preparation for its coming promotion from the “experimental” namespace. Be sure to reference the official documentation for the most up-to-date details.