55

I want to create an extension that redirects the user to another website if he clicks on the extension button. So far I have only seen extensions which create a new tab for each click.

Is it possible to redirect the user to another website using the active tab?

I tried something like this:

chrome.browserAction.onClicked.addListener(function(tab) {
    var url = "https://www.mipanga.com/Content/Submit?url="
        + encodeURIComponent(tab.url)
        + "&title=" + encodeURIComponent(tab.title);

    document.location.href = url; // <-- this does not work
});
Pang
  • 9,564
  • 146
  • 81
  • 122

4 Answers4

89

Attention: If you develop cross-browser extensions (I hope you do!), I recommend that you use chrome.tabs.query(). Please see Jean-Marc Amon's answer for more information. This answer still works in both Firefox and Chrome, but query() is more commonly used, has more options, and works in background pages and popup views.

Additional: Be aware that you cannot use the Tabs API from content scripts. As per the documentation page - "The Tabs API can be used by the service worker and extension pages, but not content scripts". If you have a need to use the Tabs API using content scripts then I would suggest looking at the Messaging API.

From the chrome.tabs API, you can use getCurrent(), query(), or update().

Right now, I prefer update() as this allows you to update the current tab without needing to do much else.

If updating the url from a content script is required then you should look to use query instead. Jean-Marc Amon's answer provides a wonderful example of how to get the active tab in this case (don't forget to upvote him!).

update()

let myNewUrl = `https://www.mipanga.com/Content/Submit?url=${encodeURIComponent(tab.url)}&title=${encodeURIComponent(tab.title)}`;
chrome.tabs.update(undefined, { url: myNewUrl });

Here, we have set the first argument of update to undefined. This is the tab id that you're wanting to update. If it's undefined then Chrome will update the current tab in the current window.

Please see Domino's answer for more information on update and also note that undefined is not needed. Again, please don't forget to upvote their answer as well if you find it useful.

getCurrent()

getCurrent also cannot be called from a non-tab context (eg a background page or popup view).

Once you have the current tab, simply pass update().

chrome.tabs.getCurrent(function (tab) {
  //Your code below...
  let myNewUrl = `https://www.mipanga.com/Content/Submit?url=${encodeURIComponent(tab.url)}&title=${encodeURIComponent(tab.title)}`;

  //Update the url here.
  chrome.tabs.update(tab.id, { url: myNewUrl });
});

NB: In order to use this this functionality, you must ensure that you have the tabs permission enabled in your manifest.json file:

"permissions": [
  "tabs"
],

Messaging API

As per the documentation page - The Tabs API can be used by the service worker and extension pages, but not content scripts.

See the answer by TimS which alludes to this. Please upvote them!

Example of interacting with the Tabs API using a service worker via the Messaging API: https://github.com/Omicron18/nitter-extension

Dan Atkinson
  • 11,391
  • 14
  • 81
  • 114
  • 1
    can we include this code in our external js file? or it has to be on the chrome popup.html? thanks! – Toni Michel Caubet Feb 20 '11 at 22:00
  • @Toni - Yes, it can be called from an external file. – Dan Atkinson Feb 21 '11 at 10:39
  • @Dan I suggest you have a look at the documentation on tabs, as it may have changed somewhat. That said, this same code works on the latest dev build of Chrome (21.0.1171.0 dev-m) for me without issue. To be honest, I'd be surprised if it didn't as Google do keep developers up to date, and my own extensions use the same sort of logic as well. If such a major part of the extensions functionality suddenly changed without warning, there'd be something of a backlash. Docs: http://code.google.com/chrome/extensions/tabs.html – Dan Atkinson Jun 13 '12 at 08:20
  • 2
    I had the same issue with chrome.tabs.getCurrent(function(tab){}) , I used chrome.tabs.getSelected(null, function(tab){}) instead and it works fine – jobwat Nov 13 '13 at 23:44
  • @jobwat Thanks! I've added it as another example. – Dan Atkinson Nov 14 '13 at 09:08
  • 1
    For posterity, I removed [`getSelected`](https://developer.chrome.com/extensions/tabs#method-getSelected) which was deprecated in v33. You should only use `query` or `getCurrent`. – Dan Atkinson Feb 26 '19 at 14:00
  • I have tried this method, but the url turns turn out to be unexpected: chrome://extension// How to remove the unwanted prefix? – Cảnh Toàn Nguyễn Mar 22 '19 at 13:38
  • @CảnhToànNguyễn What unwanted prefix? – Dan Atkinson Apr 01 '19 at 12:41
  • Is there any way where we can stop the reload/refresh of the page and just change the URL? A regular history state push won't work due to having a different domain. – sshanzel Jun 21 '22 at 09:28
  • @sshanzel: No. That's not how browsers work, and I'd be surprised if that does work, given the possible security implications (making people think you're on one site but you're actually on a malicious site). One possible alternative is to use link text fragment hashes (e.g. mydomain.com#foo). These _shouldn't_ reload the page, but you never know with Google. – Dan Atkinson Jun 21 '22 at 11:29
  • @DanAtkinson I was having the same thoughts, I was just wondering if there was any workaround, as I have two different domains trying to tie together. Thanks. – sshanzel Jun 22 '22 at 07:18
  • @sshanzel There should not be a workaround to this beyond the link text fragment hashes I mentioned previously. Trying to change the url without wanting the page to reload will not solve anything - at least nothing legitimate that I can think of. – Dan Atkinson Jun 22 '22 at 21:27
  • Jean-Marc Amon's answer doesn't work in content scripts – palapapa Jun 12 '23 at 17:44
48

You can use chrome.tabs.query too

chrome.tabs.query({currentWindow: true, active: true}, function (tab) {
      chrome.tabs.update(tab.id, {url: your_new_url});
});
Jean-Marc Amon
  • 969
  • 13
  • 16
13

The chrome.tabs.update method will automatically run on the current active tab if no tab id is passed.

This has the added advantage of not requiring the tabs permission. Extensions with this permission warn the user that they can read the browsing history, so you should avoid asking for it if you don't need to.

Changing the current tab's URL is as simple as writing this:

chrome.tabs.update(undefined, {url: 'http://example.com'});

Or as mentionned by farwayer in the comments, you don't need to put two arguments at all.

chrome.tabs.update({url: 'http://example.com'});
Domino
  • 6,314
  • 1
  • 32
  • 58
  • Works. Thanks you! – Karl Pokus Feb 07 '17 at 15:04
  • can you use that code to add a text string to the current URL? ie. add '&sandbox=true' to the current URL? – scott.schaffer Mar 09 '17 at 16:19
  • @scott.schaffer I think you'll need the `tabs` permission for that, since you'll need to retrieve the current URL of the tab before adding to it. – Domino Mar 09 '17 at 19:02
  • 2
    You can even skip first parameter `chrome.tabs.update({url: 'http://example.com'});` – farwayer Aug 30 '17 at 03:15
  • @farwayer I was not aware of that. It's true that the only thing the API page says is that the id is "optional". I probably assumed we still had to pass undefined to it since that's how I always implement functions that take some optional arguments in other positions but the last. – Domino Aug 30 '17 at 04:32
  • I have tried this method, but the url turns turn out to be unexpected: chrome://extension// How to remove the unwanted prefix? – Cảnh Toàn Nguyễn Mar 22 '19 at 13:37
  • 1
    @CảnhToànNguyễn Sounds like you might be passing a relative URL to chrome.tabs.update. Make sure you pass in a full url including a protocol. If that's not it, then you should probably open your own StackOverflow question. – Domino Mar 22 '19 at 14:56
  • Your prediction is correct. After having added protocol to URL, it works as expected. +1 vote for your comment ;) – Cảnh Toàn Nguyễn Mar 23 '19 at 09:46
  • the documentation says you should provide the tab Id, `chrome.tabs.update(integer tabId, object updateProperties, function callback)` – Anastasis Jan 15 '20 at 16:47
  • @KevinOrfas as of today, the detailed documentation still says that the tabId is optional and defaults to the currently selected tab. See the [Chrome API documentation](https://developer.chrome.com/extensions/tabs#method-update) or the [WebExtensions documentation on MDN](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/update) – Domino Jan 15 '20 at 19:58
  • @Domino Sure my bad – Anastasis Jan 16 '20 at 09:04
2

The answers given here no longer work: the Chrome Tabs API can no longer be used by content scripts, only by service workers and extension pages.

Instead, you can send a message to a service worker to get it to update the location of the current tab: see https://stackoverflow.com/a/62461987.

See this for a simple working example.

TimS
  • 92
  • 8