JavaScript URLs: The SEO, A11y & Security Fix Guide
August 26, 2026


What Is a JavaScript URL (the javascript: Pseudo-Protocol)?
A javascript: URL — the javascript pseudo-protocol — is a value placed inside an href attribute that tells the browser to execute a script snippet instead of navigating. The most common form:
Click me
javascript:void(0) runs whatever follows javascript: and discards the result with void(), preventing the browser from replacing page content with the return value. It became popular as an easy way to make an tag "clickable" without a real destination — no reload, no jump to the top of the page like a bare href="#" causes.
The problem: this one line quietly creates three separate failures — a crawlability gap that hides content from Google, an accessibility break for anyone not using a mouse, and a documented cross-site scripting entry point. Each deserves explanation, though the fix is the same for all three.
The SEO Problem: Googlebot Can't Reliably Follow Them
Google's crawling guidance is direct: to be treated as a crawlable link, an tag needs a real URL in its href attribute. When href contains javascript:void(0) instead of an actual path, Googlebot has nothing to extract, so the link is effectively invisible for crawling and indexing — confirmed in Google's link best practices documentation.
So a javascript url behaves like a missing href: no link equity flows through it, the destination gets no internal-linking signal, and if that page has no other discoverable path, it may never be indexed. Google's Martin Splitt has made the same point repeatedly in Search Central discussions: Googlebot doesn't execute onclick handlers to discover navigation, it parses href values. If your primary navigation, pagination, or product links rely on javascript: hrefs, you're asking Google to guess at a site structure it can't see. This is a close cousin of the malformed-URL problem — a link exists in the DOM but resolves to nothing a crawler can follow. See malformed URLs and how to fix them for a related category of broken href.
The Accessibility Problem: Broken Experience for Screen Readers and Keyboard Users
Screen readers and keyboard navigation depend on href carrying real, predictable information. When a link's destination is javascript:void(0), assistive technology has nothing meaningful to announce — the user hears "link" with no indication of where it goes, because there's nowhere to go. That breaks a core expectation in WCAG guidance: links should navigate, and controls that trigger actions should be marked up as controls.
Keyboard users face a related issue: native anchors are focusable and activate with Enter by default, but developers pairing javascript: hrefs with onclick handlers often wire them to fire only on mouse clicks, silently excluding anyone tabbing through the page. Lighthouse and most accessibility auditors flag this pattern because it conflates "link" semantics with "button" behavior — screen reader users can't distinguish a real navigational link from a fake one until they activate it and nothing happens.
The Security Problem: javascript: URLs as an XSS Vector
Beyond SEO and accessibility, the javascript: scheme is a documented XSS injection point. Because the browser executes anything following javascript: in an href or src attribute, that attribute becomes a direct code-execution channel — no
This keeps a crawlable, accessible href in place while giving you full control over client-side behavior — including apps using the History API for pushState routing.
If it doesn't navigate at all — a dropdown toggle, a modal opener, a "load more" trigger — it isn't a link and shouldn't be marked up as one. Use a native instead. Buttons are keyboard-accessible out of the box, announce correctly to screen readers as controls (not broken links), and carry no href for crawlers to misinterpret:
As defense-in-depth against XSS, pair this with a Content Security Policy (CSP) that restricts inline script execution — it won't fix a bad href pattern, but it limits the blast radius if one slips through.
How to Find Every javascript: URL on Your Site
On a small site, view-source or your browser's inspect-element panel plus a quick search for javascript: in the page source will surface obvious offenders. That works for one page, but it doesn't scale — templated navigation, footers, and third-party widgets tend to repeat the same broken pattern across hundreds of pages, and manual page-by-page searching misses most of them.
An automated crawl is faster: it should walk your full site, flag every href starting with javascript:, and cross-reference those against your accessibility and crawlability audit results in one pass, rather than three separate reports.
Get an Automated Audit Instead of a Manual Grep
Hunting through source code for every javascript:void(0) instance across a large site is tedious and easy to get wrong. Optimevra runs that audit automatically, flagging javascript URLs alongside other broken-link and conversion-killing patterns across your entire site in one scan. If you'd rather see it in action first, check the live demo before running your own audit.
Frequently Asked Questions
Is href="#" bad for SEO?
Yes — it's functionally equivalent to a missing href as far as Google is concerned. Googlebot extracts links from real URLs in the href attribute, so javascript:void(0) passes no link equity and signals no site structure, which can leave dependent pages under-crawled or unindexed.
Can Google crawl or follow javascript: links at all?
No, not reliably. Google's crawling documentation states crawlable links need an actual URL in the href attribute; javascript: pseudo-protocol values don't meet that bar, so Googlebot treats those links as non-navigable.
Why do developers still use javascript: URLs if they're risky?
Mostly habit and convenience — it was historically an easy way to make an element clickable without a real destination or a page jump. It predates wider adoption of preventDefault() and native elements, and the pattern often just gets copied forward in templates.
What should I use instead of javascript:void(0) for buttons and links?
Use a real with event.preventDefault() for anything that navigates, and a native for anything that only triggers an action like a modal or toggle. This preserves crawlability, keyboard accessibility, and correct screen reader announcements.
Can a javascript: URL actually be a security vulnerability?
Yes — the javascript: scheme executes arbitrary code directly from an href or src attribute, making it a documented XSS injection point. It becomes dangerous the moment any part of that href is built from unsanitized user input, query parameters, or CMS content.
Do screen readers announce javascript: links properly?
No. Since there's no real destination, assistive technology announces the element as a generic link with no meaningful target, which violates WCAG expectations that links convey a clear destination and controls are marked up as controls.
Originally published on Rankevra.