</>
character.codes
← Back to Learn

HTML Special Characters in Forms, URLs, and JSON

Published March 15, 2025

The five reserved HTML characters

Five characters have special meaning in HTML and must be escaped when you want to display them as literal text:

CharacterEntityWhy it's reserved
<&lt;Opens an HTML tag
>&gt;Closes an HTML tag
&&amp;Starts an entity reference
"&quot;Delimits attribute values
'&apos;Alternative attribute delimiter

Escaping in HTML body text

Inside element content, you must escape < and &. It's good practice to escape > too, although browsers generally handle it unescaped. If you write <p>5 &lt; 10</p>, the browser displays “5 < 10” correctly instead of trying to parse a tag.

Escaping in HTML attributes

Inside attribute values, you must escape the quote character that matches the delimiter. If the attribute uses double quotes, escape " as &quot;. Always quote your attribute values — unquoted attributes are a common source of XSS vulnerabilities because spaces or other characters can break out of the value.

<!-- Safe: quotes are escaped -->
<input value="He said &quot;hello&quot;">

<!-- Dangerous: unquoted attribute -->
<input value=user_input>

Escaping in JavaScript strings

In inline <script> blocks, the HTML parser takes precedence. The sequence </script> appearing anywhere — even inside a string literal — will close the script element. To avoid this:

  • Split the closing tag: "</" + "script>"
  • Use Unicode escapes: "\u003c/script>"
  • Or better yet, avoid inline scripts and use external files or JSON.stringify() for dynamic data

Escaping in JSON

JSON requires escaping double quotes (\"), backslashes (\\), and control characters. Newlines become \n, tabs become \t. Any character can be represented with a Unicode escape: \u00A9 for ©.

Always use JSON.stringify() to generate JSON programmatically. Manual string building is a recipe for malformed output and injection bugs.

Escaping in URLs

URLs use percent-encoding for characters outside the unreserved set. A space becomes %20, an ampersand becomes %26. In JavaScript:

  • encodeURIComponent() encodes a single query parameter value (escapes &, =, ?, etc.)
  • encodeURI() encodes a full URI (preserves :, /, ?, &)

When building URLs with user input, always encode parameter values with encodeURIComponent() to prevent parameter injection.

Preventing XSS

Cross-site scripting (XSS) occurs when an attacker injects malicious scripts through unescaped user input. Key defenses:

  • Never insert user input as raw HTML. Use textContent instead of innerHTML
  • Use framework auto-escaping — React, Vue, Angular, and Svelte all escape interpolated values by default
  • Set a Content Security Policy header to restrict script sources
  • Sanitize HTML if you must accept rich text (use a library like DOMPurify, never regex)

Common mistakes

  • Double-encoding: escaping an already-escaped string turns &amp; into &amp;amp;, which displays as “&amp;” instead of “&”
  • Forgetting attribute escaping: a user's name containing a quote can break out of an attribute and inject HTML
  • Trusting client-side sanitization: always sanitize on the server too, since client-side checks can be bypassed
  • Mixing encoding contexts: HTML-escaping a value that goes into a URL, or URL-encoding a value that goes into HTML, produces gibberish