Bookmarklet for Archive.is to navigate to the canonical link with the “redirected from” instead of “saved from”
Posted by jpluimers on 2026/01/27
This is a follow-up on Bookmarklet for Archive.is to navigate to the canonical link which can be accessed from multiple URLs, some through redirection:
- https://wiert.wordpress.com/?p=101586
- https://wiert.me/2023/08/15/bookmarklet-for-archive-is-to-navivate-to-the-canonical-link/
You can see the difference in these archived links (the navivate was a typo that I only spotted after the original blog post got published):
I wanted a Bookmarklet to find the last link; the one in the referenced blog post didn’t.
The actual use case leading to document all this was the Archive.is archived version of archive.org/download/beagle.applearchives.composters/Poster%2010.pdf (more on the posters in slightly less than a year at the blog post Beagle Bros recreated in modern color… | Applefritter).
That archived version can be reached through these URLs:
- short archive.is/jY2Ri
- redirected to archive.is/2025.10.27-120705/https://ia800307.us.archive.org/34/items/beagle.applearchives.composters/Poster%2010.pdf
- redirected from archive.is/2025.10.27-120705/https://archive.org/download/beagle.applearchives.composters/Poster%2010.pdf
Inspiration for the below script is from another set of Bookmarklets I blogged about in The JavaScript bookmarklets that saved me a lot of time documenting the Embarcadero docwiki outage.
I first hesitated a bit to use the ` based template strings in that blog post, and opted to use join instead inspired by [Wayback/Archive] How can I build/concatenate strings in JavaScript? – Stack Overflow (thanks [Wayback/Archive] MrHaze and [Wayback/Archive] typically) which shows both methods combined.
Later I decided to revert, as using join, see below why.
Documentation for both methods is here:
- [Wayback/Archive]
Array.prototype.join()– JavaScript | MDN has an optionalseparatorargument defaulting to a comma (,):
The
join()method ofArrayinstances creates and returns a new string by concatenating all of the elements in this array, separated by commas or a specified separator string. If the array has only one item, then that item will be returned without using the separator. - [Wayback/Archive] Template strings – JavaScript | MDN which redirects to [Wayback/Archive] Template literals (Template strings) – JavaScript | MDN is very versatile:
Template literals are literals delimited with backtick (
`) characters, allowing for multi-line strings, string interpolation with embedded expressions, and special constructs called tagged templates.
Oh: one reason for not using template literals is that it is way easier to embed a one-liner into something like js-tokenizer for syntax highlighting.
Note that:
- the
?.operator prevents error messages when one or more of the queries return no output. The end result is one or moreundefinedto appear in the navigated URL. That’s better than crashing without navigating and having to check the browser debugger why that happened - I wipe most of the
anchor(basically everything on the right side) because setting thepathnamewill not clear thesearch(query) andhash(fragment) parts ifredirectFromdoes not have those. This sort of makes the starting point a Clean URL as much as possible. - I now prefer the
`version as the second note in this list caused thejoinconstruct to need two of them: one for the separator bit, and the other with an empty separator. This made the code too convoluted.
join version of the Bookmarklet script
javascript: (function() {
canonical = document.querySelector('link[rel="canonical"]')?.href;
anchor = document.createElement("a");
anchor.href = canonical;
pathname = anchor.pathname;
separator = "/";
splitPathname = pathname.split(separator);
timestamp = splitPathname[1];
redirectFrom = document.querySelectorAll('input[readonly]')[0]?.value;
anchor.pathname = "";
anchor.search = "";
anchor.fragment = "";
hrefLeftParts = [anchor.href, timestamp];
hrefLeft = hrefLeftParts.join("");
hrefFullParts = [hrefLeft, redirectFrom];
href = hrefFullParts.join(separator);
location = href;
})();
As one-liner:
javascript:(function(){canonical = document.querySelector('link[rel="canonical"]')?.href; anchor = document.createElement("a"); anchor.href = canonical; pathname = anchor.pathname; separator = "/"; splitPathname = pathname.split(separator); timestamp = splitPathname[1]; redirectFrom = document.querySelectorAll('input[readonly]')[0]?.value; anchor.pathname = ""; anchor.search = ""; anchor.fragment = ""; hrefLeftParts = [anchor.href, timestamp]; hrefLeft = hrefLeftParts.join(""); hrefFullParts = [hrefLeft, redirectFrom]; href = hrefFullParts.join(separator); location = href;})();
` version of the Bookmarklet script
javascript: (function() {
canonical = document.querySelector('link[rel="canonical"]')?.href;
anchor = document.createElement("a");
anchor.href = canonical;
pathname = anchor.pathname;
separator = "/";
splitPathname = pathname.split(separator);
timestamp = splitPathname[1];
redirectFrom = document.querySelectorAll('input[readonly]')[0]?.value;
anchor.pathname = "";
anchor.search = "";
anchor.hash = "";
href = anchor.href;
hrefTemplate = `${href}${timestamp}${separator}${redirectFrom}`;
anchor.href = hrefTemplate;
location = anchor.href;
})();
As one-liner:
javascript:(function(){canonical = document.querySelector('link[rel="canonical"]')?.href; anchor = document.createElement("a"); anchor.href = canonical; pathname = anchor.pathname; separator = "/"; splitPathname = pathname.split(separator); timestamp = splitPathname[1]; redirectFrom = document.querySelectorAll('input[readonly]')[0]?.value; anchor.pathname = ""; anchor.search = ""; anchor.hash = ""; href = anchor.href; hrefTemplate = `${href}${timestamp}${separator}${redirectFrom}`; anchor.href = hrefTemplate; location = anchor.href;})();
Tools used
- [Wayback/Archive] Bookmarklet Maker
- [Wayback/Archive] URL Decode and Encode – Online
- [Wayback/Archive] Best Javascript Beautifier tool work as JavaScript Formatter, Viewer and Prettier
- GitHub: gist – Wikipedia
- [Wayback/Archive] index.js – nodebox – CodeSandbox – my fork to show the tokenizing of an early version of the join based Bookmarklet above
- Some links for JavaScript tokenizers and syntax highlighters
Documentation references
- [Wayback/Archive]
undefined– JavaScript | MDN - [Wayback/Archive] JavaScript data types and data structures – JavaScript | MDN
- [Wayback/Archive] Optional chaining (
?.) – JavaScript | MDN - [Wayback/Archive]
<a>: The Anchor element – HTML | MDN - [Wayback/Archive]
<input>: The HTML Input element – HTML | MDN - [Wayback/Archive] Document:
createElement()method – Web APIs | MDN - [Wayback/Archive] Document: querySelector() method – Web APIs | MDN
- [Wayback/Archive] Document:
querySelectorAll()method – Web APIs | MDN - [Wayback/Archive]
String.prototype.split()– JavaScript | MDN - URL – Wikipedia
- Uniform Resource Identifier – Wikipedia
--jeroen
Both scripts syntax highlighted from in a gist
[Wayback/Archive] Bookmarklet for Archive.is to navigate to the canonical link with the “redirected from” instead of “saved from” · GitHub
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| javascript: (function() { | |
| canonical = document.querySelector('link[rel="canonical"]')?.href; | |
| anchor = document.createElement("a"); | |
| anchor.href = canonical; | |
| pathname = anchor.pathname; | |
| separator = "/"; | |
| splitPathname = pathname.split(separator); | |
| timestamp = splitPathname[1]; | |
| redirectFrom = document.querySelectorAll('input[readonly]')[0]?.value; | |
| anchor.pathname = ""; | |
| anchor.search = ""; | |
| anchor.hash = ""; | |
| href = anchor.href; | |
| hrefTemplate = `${href}${timestamp}${separator}${redirectFrom}`; | |
| anchor.href = hrefTemplate; | |
| location = anchor.href; | |
| })(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| javascript:(function(){canonical = document.querySelector('link[rel="canonical"]')?.href; anchor = document.createElement("a"); anchor.href = canonical; pathname = anchor.pathname; separator = "/"; splitPathname = pathname.split(separator); timestamp = splitPathname[1]; redirectFrom = document.querySelectorAll('input[readonly]')[0]?.value; anchor.pathname = ""; anchor.search = ""; anchor.hash = ""; href = anchor.href; hrefTemplate = `${href}${timestamp}${separator}${redirectFrom}`; anchor.href = hrefTemplate; location = anchor.href;})(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| javascript: (function() { | |
| canonical = document.querySelector('link[rel="canonical"]')?.href; | |
| anchor = document.createElement("a"); | |
| anchor.href = canonical; | |
| pathname = anchor.pathname; | |
| separator = "/"; | |
| splitPathname = pathname.split(separator); | |
| timestamp = splitPathname[1]; | |
| redirectFrom = document.querySelectorAll('input[readonly]')[0]?.value; | |
| anchor.pathname = ""; | |
| anchor.search = ""; | |
| anchor.fragment = ""; | |
| hrefLeftParts = [anchor.href, timestamp]; | |
| hrefLeft = hrefLeftParts.join(""); | |
| hrefFullParts = [hrefLeft, redirectFrom]; | |
| href = hrefFullParts.join(separator); | |
| location = href; | |
| })(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| javascript:(function(){canonical = document.querySelector('link[rel="canonical"]')?.href; anchor = document.createElement("a"); anchor.href = canonical; pathname = anchor.pathname; separator = "/"; splitPathname = pathname.split(separator); timestamp = splitPathname[1]; redirectFrom = document.querySelectorAll('input[readonly]')[0]?.value; anchor.pathname = ""; anchor.search = ""; anchor.fragment = ""; hrefLeftParts = [anchor.href, timestamp]; hrefLeft = hrefLeftParts.join(""); hrefFullParts = [hrefLeft, redirectFrom]; href = hrefFullParts.join(separator); location = href;})(); |






Leave a comment