HTMLエスケープとは?
HTMLエスケープとは、HTML内で特別な意味を持つ文字を、対応するエンティティ参照に置き換える処理です。エスケープが必要な5つの文字は、アンパサンド(&)、小なり記号(<)、大なり記号(>)、ダブルクォート(")、シングルクォート(')です。エスケープしない場合、ブラウザはこれらの文字をマークアップの指示として解釈してしまい、ページのレンダリングが崩れたりインジェクション攻撃の糸口を与えたりします。
HTML仕様(WHATWGが管理)では、文字参照に2種類の形式が定義されています。& のような名前付きエンティティと、& や & のような数値エンティティです。名前付きエンティティはソースコードで読みやすい反面、数値エンティティ(10進数または16進数)は名前付きエイリアスのない文字も含めたあらゆる Unicode コードポイントを表現できます。どちらの形式もブラウザでは同一の出力を生成します。
アンエスケープ(デコードとも呼ばれます)はその逆の処理で、エンティティ参照をリテラルの文字に戻します。HTMLソースからテキストを抽出する場合、システム間でコンテンツを移行する場合、またはエンティティが二重エンコードされたテンプレートをデバッグする場合によく使われます。このツールはブラウザ内でどちらの方向にも変換できるため、エスケープロジックの検証やHTMLの多いソースから平文を取り出す作業が素早く行えます。
HTMLエスケープツールを使う理由
大量のテキストブロックにわたって手動で山括弧やアンパサンドを置き換えるのは手間がかかり、ミスも起きやすいです。専用ツールを使えば、インストール不要で入力を一度に変換できます。
HTMLエスケープの主な使用例
HTMLエンティティ参照表
以下の表はよく使われるHTMLエンティティの一覧です。5つの特殊文字(& < > " ')はHTMLコンテンツと属性値では必ずエスケープする必要があります。その他のエンティティは任意ですが、入力が難しい文字やソースコードで曖昧になる文字に便利です。
| 文字 | 説明 | 名前付きエンティティ | 数値エンティティ |
|---|---|---|---|
| & | Ampersand | & | & |
| < | Less-than sign | < | < |
| > | Greater-than sign | > | > |
| " | Double quote | " | " |
| ' | Single quote / apostrophe | ' | ' |
| Non-breaking space | |   | |
| © | Copyright sign | © | © |
| ® | Registered sign | ® | ® |
| — | Em dash | — | — |
| ’ | Right single quote | ’ | ’ |
| € | Euro sign | € | € |
エスケープ vs. アンエスケープ:使い分け
この2つの操作は互いに逆の変換です。方向を間違えると、二重エンコードされた出力やエスケープされていない出力が生成されます。
コード例
以下は4つの言語でのHTMLエスケープとアンエスケープの実装例です。各スニペットはネストしたクォートや数値エンティティなどのエッジケースを含む両方向の変換を扱います。
// Escape HTML entities manually
function escapeHtml(str) {
return str
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''')
}
escapeHtml('<img src="x" onerror="alert(1)">')
// → "<img src="x" onerror="alert(1)">"
// Unescape using DOMParser (browser only)
function unescapeHtml(str) {
const doc = new DOMParser().parseFromString(str, 'text/html')
return doc.documentElement.textContent
}
unescapeHtml('<div>Hello</div>')
// → "<div>Hello</div>"import html
# Escape special characters
html.escape('<script>alert("XSS")</script>')
# → '<script>alert("XSS")</script>'
# Escape including single quotes (quote=True is default in Python 3.8+)
html.escape("It's <b>bold</b>", quote=True)
# → 'It's <b>bold</b>'
# Unescape entities back to characters
html.unescape('<p>Price: €10</p>')
# → '<p>Price: €10</p>'
# Unescape numeric entities
html.unescape('<div>&amp;</div>')
# → '<div>&</div>'package main
import (
"fmt"
"html"
)
func main() {
// Escape HTML special characters
escaped := html.EscapeString(`<a href="page?id=1&sort=name">Link</a>`)
fmt.Println(escaped)
// → <a href="page?id=1&sort=name">Link</a>
// Unescape back to original
original := html.UnescapeString("<b>Go & HTML</b>")
fmt.Println(original)
// → <b>Go & HTML</b>
}<?php
// Escape HTML entities (ENT_QUOTES escapes both " and ')
echo htmlspecialchars('<p class="info">Tom & Jerry's</p>', ENT_QUOTES, 'UTF-8');
// → <p class="info">Tom & Jerry's</p>
// Convert all applicable characters to HTML entities
echo htmlentities('Price: 10€ — 50% off', ENT_QUOTES, 'UTF-8');
// → Price: 10€ — 50% off
// Decode entities back
echo html_entity_decode('<div>&copy; 2026</div>');
// → <div>© 2026</div>