Bookmarklet Generator

Write it, test it safely, drag it to the bar.

  • Sandboxed test page
  • Decodes bookmarklets
  • Ready-made library
An open silver laptop on a pale desk with a strip of white paper lying across its keyboard and a small yellow lightning bolt beside it

The guide

A Bookmarklet Runs as the Page You Are On, and That Is the Whole Deal

A bookmark whose address is code has worked since 1995 because the browser treats it as part of the page in front of you, with every right that page has.

  • 1995 year the javascript: URL arrived, by its inventor's account
  • 188 characters the worked example as a finished link, from 138 characters of source
  • 65,536 characters, the longest address a Firefox bookmark will store
  • 2 MB longest URL Chrome will handle, by Chromium's own guidelines
  • April 2013 when Firefox's bug on site policy stopping bookmarklets was filed
Read the full guide Fold the guide 7 min · 20 sources

A bookmark is supposed to hold an address. A bookmarklet holds a small program instead, and the browser runs it against whatever page is open when you click.

That was the plan from the start. In an email that Simon Willison posted to a SitePoint discussion in April 2004, Brendan Eich wrote that he invented the javascript: URL along with JavaScript in 1995, and intended such URLs to work like any other kind, including being bookmarkable. He added that the void operator went into the language before Netscape 2 shipped, to make it easy to discard a value. Netscape’s own guide, last updated in October 1997, then showed how to put a command on the Personal Toolbar of Navigator 4.0: create a bookmark, and type javascript:void(command) into the field where the location would go.

The name came later. Wikipedia credits Steve Kangas, whose bookmarklets.com was registered in April 1998, with coining the word.

Jesse Ruderman’s long-running collection describes the result as free tools to help with repetitive or otherwise impossible tasks in your web browser. That is still the appeal. No store, no installer, no update channel. One link, dragged to a toolbar.

How the browser reads the address

The HTML Standard spells out what a click does. The browser serializes the URL, removes the leading javascript:, percent-decodes what is left, decodes those bytes as UTF-8, and runs the text as a classic script with the settings of the document on screen. Then it looks at the value the script ended on. If that value is a string, the browser builds a new document from it, and the page you were reading is gone. Any other outcome leaves the page alone. An attempt in 2010 to describe the scheme in an IETF draft expired the following March. The browser standard is where the behavior is written down now.

That string rule is why void matters. MDN’s reference recommends putting void in front of a script that ends with a function call, in case the function happens to return a string, and its page on the operator describes browsers replacing the page with any returned value that is not undefined. Netscape’s 1997 instruction made the same point: using void ensures that the original page is left unchanged. Ending a script with void 0 costs seven characters and removes the question.

The function wrapper solves a different problem. A script run this way shares the page’s global scope, so a name declared at the top level becomes a name of the page, where it can collide with the site’s own code or with the same bookmarklet clicked a second time. Inside a function, the names stay inside.

Then there is the trip through the address itself. The URL Standard’s parser trims spaces from both ends of an address and removes every tab and line break inside it, so a script pasted in raw loses its line structure before it runs, and a comment that began with two slashes swallows whatever followed it. A percent sign followed by two hex digits is read as an escape. Percent-encoding the script avoids both problems: a line break travels as %0A and arrives as a line break. Those line breaks carry meaning. ECMAScript inserts a missing semicolon only where a line terminator separates two tokens, and it counts a comment that spans lines as a line terminator too.

So a careful generator strips comments and indentation but never joins two lines. Joining them is how one assignment on each of two lines, with no semicolons, turns into a syntax error.

Take three lines: a comment, a line that collects every link with document.querySelectorAll, and a line that calls alert with the count and the page title. That source is 138 characters long. Stripping removes the comment and the last line break and leaves 104. Wrapping the code in a function and ending with void 0 brings the script to 129. Encoding then replaces 24 of those characters, the spaces, line breaks, semicolons, braces, brackets, plus signs and the equals sign, with three characters each, which adds 48. The scheme adds 11 more. The finished link is 188 characters, and the tool on this page shows the same three numbers for its starting code: 138, 104 and 188.

Run it on the sample page in the test bench and the log reads: alert: 6 links on Field Notes: a morning at the marsh. Switch stripping off and the link grows to 242 characters, with nothing gained.

What it can see

Because the script runs with the document’s own settings, it is not a guest. It can read what the page’s scripts can read: the text, the form fields, whatever cookies and storage are open to script. It can also send requests that carry your login. That is what makes a bookmarklet useful on a page you are signed in to, and it is the entire security question. A bookmarklet from a stranger, clicked on your bank’s site, acts as you. The expired IETF draft put it dryly in its security section: evaluation in context necessitates extreme caution in deciding where such identifiers are recognized and what facilities are made available to the script.

Browser makers treat pasted code as a known trap. The Chrome DevTools team defines self-XSS as a social engineering attack that tricks you into executing malicious code in your web browser, and its console now refuses a first paste until you type the words allow pasting. Chromium’s address bar code strips a leading javascript: from text pasted into it. A bookmark has no such speed bump. Once saved, it runs on every click.

Where the policy says no

Content Security Policy lets a site declare which scripts may run on its pages. The W3C draft is explicit that this should not catch bookmarklets: policy enforced on a resource should not interfere with the operation of user-agent features like addons, extensions, or bookmarklets, because such features advance the user’s priority over page authors. The idea behind that line is older and comes from the HTML design principles: in case of conflict, consider users over authors. Practice has been rougher. MDN warns that javascript: navigation may be blocked by a site’s policy, script-src in particular, and the Firefox bug titled Bookmarklets affected by CSP, filed in April 2013, still carried the status NEW in October 2026.

Even where the click itself is allowed, the policy goes on governing what the script does next. A bookmarklet that tries to pull its real code from another server, or to send data to one, meets the same rules as the page’s own scripts. The sample page in the bench is built that way on purpose, and it logs every refused request.

The practical rule follows. Prefer bookmarklets that carry all of their code and change the page with plain DOM calls. They have fewer ways to be refused, and there is less to read.

Phones and tablets

A phone has no toolbar to drag a link to. The way in is the one Netscape printed in 1997: make an ordinary bookmark, then edit it and replace its address with the javascript: URL. Paul Adam’s instructions for his accessibility bookmarklets give exactly those steps for Safari on the iPhone: bookmark a page, edit the bookmark, delete its address, paste the code and save. Chrome’s help for Android puts Edit in the menu beside each bookmark. Chrome’s page does not mention scripts, so whether the edited bookmark then runs is something to test on your own device, not assume. Pasting the URL into the address bar is no substitute in Chrome, since Chromium drops the scheme from pasted text.

Length is rarely the obstacle. Firefox’s source refuses a bookmark address longer than 65,536 characters, a cap that its own comment says is imposed to limit database size. Chromium’s guidelines put the longest URL that Chrome will handle at 2 MB. No comparable figure was found for Safari, so none is given here.

Reading one before you trust it

The decoding a browser does can be done by eye. Undo the percent escapes, break the script into lines, and look for a short list of things. First come calls that reach the network, such as fetch, XMLHttpRequest, sendBeacon, a new Image, or a created script or iframe. Then cookies and storage, form values and password fields, eval and the Function constructor, the clipboard, and any host name sitting in a string. A script that builds a script element pointing at someone’s server is the one to stop at, because what you read today is not what that server has to send tomorrow.

This kind of reading has hard limits, and the tool here shares them. Its inspector is a search for tokens. It cannot follow a name assembled from pieces at run time, so an empty result proves nothing. Its test bench runs code inside a sandboxed frame, which MDN describes as a special origin that always fails the same-origin policy. There are no cookies there, no saved login and no real site. A bookmarklet that behaves in the bench may behave differently where it matters, and one that never finishes can freeze the tab.

None of that is an argument against them. A bookmarklet is one of the last places on the web where a reader can change a page on a whim, with a tool small enough to read in full. Read it. Then drag it to the bar.

Sources

Every source consulted for this guide. Links checked October 7, 2026.

  1. HTML Standard WHATWG
  2. URL Standard WHATWG
  3. javascript: URLs MDN Web Docs
  4. void operator MDN Web Docs
  5. <iframe> HTML inline frame element MDN Web Docs
  6. ECMAScript® 2027 Language Specification Ecma International, TC39
  7. Content Security Policy Level 3 World Wide Web Consortium
  8. HTML Design Principles World Wide Web Consortium
  9. 866522 - Bookmarklets affected by CSP Mozilla Bugzilla
  10. The 'javascript' resource identifier scheme IETF Datatracker
  11. Miscellaneous Features Netscape Communications Corporation, kept by the Internet Archive
  12. Bookmarklets SitePoint, kept by the Internet Archive
  13. Bookmarklet Wikipedia
  14. Jesse's Bookmarklets Site Jesse Ruderman
  15. How Chrome DevTools helps to defend against self-XSS attacks Chrome for Developers
  16. components/omnibox/browser/omnibox_text_util.cc - chromium/src - Git at Google The Chromium Authors
  17. Guidelines for URL Display Chromium Docs
  18. PlacesUtils.sys.mjs - mozsearch Mozilla, Firefox source on Searchfox
  19. Install Bookmarklets for Accessibility Testing Directly on iOS Device Paul J. Adam
  20. Create, find and edit bookmarks in Chrome Google Chrome Help