中学理科1630686 views
小学社会310495 views
数学講師2886596 views
ヒストリア290629 views
雑学1473627 views
英語613685 views
MathPython497416 views
りんご209693 views
小学理科719898 views
高校化学2924523 views
Help
Tools
NewsSpreadsheetCalendarBookkeepingMarkdown TablesLanguage Model NewsSlidesTier ListPen ToolIllustrationCrayonWatercolorPixel ArtASCII ArtPerspectiveEndless StairsGraphMind MapER DiagramFamily TreeMemeCurved TextImage EditorMosaicRetro FilterPencil SketchSwirl EffectLine ArtOCR/HighlighterMakeup EditorFaviconVideo TrimmerScrolling VideoVideo TitleColor PickerColor ExtractorBonfireFireworksCherry BlossomWater RippleWater SplashBreaking GlassGlass TextureFabric TextureWood GrainMarble TextureBrick Wall TextureMetal TextureWashi Paper TextureCardboard TextureCSS ButtonIcon MakerBar ChartGrouped Bar ChartStacked Bar ChartPie ChartLine ChartArea ChartStacked Area ChartScatter Plot3D Bar Chart3D Pie ChartBar Chart RaceBubble ChartPopulation PyramidPictogramEarningsCandlestick ChartInvestment RiskMortgage SimulatorCalculatorMatrix CalculatorFunction GraphPolynomial ExpansionVenn DiagramField VisualizerRubik's Cube Group TheoryTraveling SalesmanVoronoi and DelaunayFractalColumn ArithmeticDraw Math FiguresArithmetic AnimationArithmetic Word ProblemsCounting with Tree DiagramsCube NetsRolling DiceCross SectionsMotion PathMechanicsWavesElectromagnetic WavesCapacitorsLight and LensesThermodynamicsHow Semiconductors WorkMolecular StructuresAtomic OrbitalsElectrochemical CellsChemical EquilibriumCrystal LatticesBuffer pHOrganic Reaction MapPeriodic TableComplex IonsDNA Double HelixCell DivisionMembrane ChannelsNerve ImpulseMuscle ContractionHormones and HomeostasisRock ClassificationWeatherConstellationsSolar and Lunar Eclipses3D ModelingFloor PlanSeismic StructuresIntersection TurnMaglevCooking AnimationOrigamiLive Viewer CountGeoJSON MapRailway MapPopulation MapCrime MapLand Price MapSchool MapShrine and Castle MapHouse of Representatives MapWord MapSolitaireReversiHakoiri MusumeChessHamburgerRippleSlide Puzzle MakerNeon PinballNovel MakerJapanese Typing PracticePiano Score EditorMusic TheoryShogi StrategyPiano Rhythm Game

English

URL に日本語や記号を含めるときのエンコード - encodeURI と encodeURIComponent の使い分け

URL に日本語やスペース、記号を含めると文字化けやリンク切れが起きることがある。JavaScript には encodeURI と encodeURIComponent という似た名前の関数があるが、使い分けを間違えると URL が壊れる。この記事ではパーセントエンコーディングの仕組みから、2 つの関数の違いと実務での使い方を解説する。

パーセントエンコーディングとは

URL に使える文字は ASCII の一部に限られている。RFC 3986 では、エンコードなしで使える文字(非予約文字)を以下のように定めている。

英字(A-Z, a-z)
数字(0-9)
ハイフン、ピリオド、アンダースコア、チルダ(- . _ ~)

これ以外の文字を URL に含めるには、その文字の UTF-8 バイト列を % に続く 16 進数 2 桁で表す「パーセントエンコーディング」が必要になる。

// 「東京」を UTF-8 でエンコードすると
// 東 → E6 9D B1 → %E6%9D%B1
// 京 → E4 BA AC → %E4%BA%AC

console.log(encodeURIComponent('東京'));
// → %E6%9D%B1%E4%BA%AC

ブラウザのアドレスバーでは日本語がそのまま表示されることが多いが、実際に送信される HTTP リクエストではパーセントエンコーディングされた文字列が使われている。

予約文字という概念

URL には構造上の意味を持つ「予約文字」が存在する。

文字URL 内での役割
:スキームとホストの区切り
/パスの区切り
?クエリの開始
&クエリパラメータの区切り
=キーと値の区切り
#フラグメントの開始

これらの文字はエンコードすべき場面とすべきでない場面がある。URL の構造を作るために使うなら生のまま、データとして含めるならエンコードが必要だ。この判断の違いが encodeURI と encodeURIComponent の役割を分ける。

encodeURI の動作

encodeURI は URL 全体をエンコードするための関数で、URL の構造に関わる予約文字はエンコードしない。

const url = 'https://example.com/検索結果?q=東京タワー&page=1';

console.log(encodeURI(url));
// → https://example.com/%E6%A4%9C%E7%B4%A2%E7%B5%90%E6%9E%9C?q=%E6%9D%B1%E4%BA%AC%E3%82%BF%E3%83%AF%E3%83%BC&page=1

:// や ? や & はそのまま残り、日本語だけがエンコードされている。URL の形を保ったまま、ASCII 以外の文字だけを安全な表現に変換するのが encodeURI の役割だ。

encodeURI がエンコードしない文字は、非予約文字(英数字と - . _ ~)に加えて、予約文字(: / ? # [ ] @ ! $ & ’ ( ) * + , ; =)とパーセント記号 % である。

URL の構造を形成する文字群。encodeURI はこれらを「URL の一部」とみなして変換しない。

encodeURIComponent の動作

encodeURIComponent は URL の部品(パラメータの値など)をエンコードするための関数で、予約文字もエンコードする。

const value = '東京タワー&スカイツリー';

console.log(encodeURIComponent(value));
// → %E6%9D%B1%E4%BA%AC%E3%82%BF%E3%83%AF%E3%83%BC%26%E3%82%B9%E3%82%AB%E3%82%A4%E3%83%84%E3%83%AA%E3%83%BC

& が %26 にエンコードされている点に注目してほしい。もしこの値を encodeURI でエンコードしていたら、& がそのまま残り、クエリパラメータの区切りとして誤解釈されてしまう。

encodeURI

URL 全体に使う。予約文字を保持するため、URL の構造が壊れない。パラメータの値に予約文字が含まれると問題が起きる。

encodeURIComponent

URL の部品(パラメータの値やパスの一部)に使う。予約文字もエンコードするため、データとして安全に渡せる。URL 全体に使うと構造が壊れる。

誤用するとどうなるか

2 つの関数を逆に使った場合の問題を具体的に見てみよう。

HTML
CSS
JavaScript
<div id="demo">
    <div class="case">
        <h2>ケース 1: URL 全体に encodeURIComponent を使う(誤り)</h2>
        <p id="case1" class="result"></p>
    </div>
    <div class="case">
        <h2>ケース 2: パラメータ値に encodeURI を使う(誤り)</h2>
        <p id="case2" class="result"></p>
    </div>
    <div class="case">
        <h2>ケース 3: 正しい使い分け</h2>
        <p id="case3" class="result"></p>
    </div>
</div>
#demo {
    font-family: monospace;
    font-size: 13px;
}
h2 {
    font-size: 13px;
    margin-bottom: 4px;
}
.case {
    margin-bottom: 16px;
}
.result {
    background: #1e1e1e;
    color: #d4d4d4;
    padding: 8px 12px;
    border-radius: 4px;
    word-break: break-all;
    line-height: 1.5;
}
.bad {
    border-left: 3px solid #f44;
}
.good {
    border-left: 3px solid #4caf50;
}
var base = 'https://example.com/search';
var query = 'price=100&200';

var case1 = encodeURIComponent(base + '?q=' + query);
var el1 = document.getElementById('case1');
el1.textContent = case1;
el1.className = 'result bad';

var case2 = base + '?q=' + encodeURI(query);
var el2 = document.getElementById('case2');
el2.textContent = case2;
el2.className = 'result bad';

var case3 = base + '?q=' + encodeURIComponent(query);
var el3 = document.getElementById('case3');
el3.textContent = case3;
el3.className = 'result good';

ケース 1 では :// や ? までエンコードされて URL として機能しなくなっている。ケース 2 では & がそのまま残り、“200” が別のパラメータとして分離されてしまう。ケース 3 のように、URL の構造部分はそのまま組み立て、値の部分だけ encodeURIComponent でエンコードするのが正しい。

実務でのパターン

よくある場面ごとに、どちらの関数を使うべきかを整理する。

クエリパラメータの値

encodeURIComponent を使う。ユーザー入力をそのまま URL に埋め込むと、& や = が構造を壊す危険がある。

パスの一部

encodeURIComponent を使う。日本語のカテゴリ名やファイル名をパスに含めるときに必要。ただし / はエンコードされるため、パス区切りは自分で組み立てる。

URL 全体の一括変換

encodeURI を使う。既に構造が完成している URL の中の非 ASCII 文字だけを変換したいとき。ただしパラメータ値の安全性は保証されない。

リダイレクト先 URL をパラメータに含める

encodeURIComponent を使う。URL の中に別の URL を埋め込むときは、内側の URL の予約文字をすべてエンコードする必要がある。

リダイレクト URL の埋め込みは特に間違いやすいパターンだ。

// リダイレクト先 URL をパラメータに含める
const redirectUrl = 'https://example.com/callback?token=abc';

// 誤り: encodeURI だと ? や = が残り、外側の URL 構造を壊す
const bad = 'https://auth.example.com/login?redirect=' + encodeURI(redirectUrl);
// → https://auth.example.com/login?redirect=https://example.com/callback?token=abc
// → ?token=abc が外側のパラメータとして解釈される

// 正しい: encodeURIComponent で内側の URL をまるごとエンコード
const good = 'https://auth.example.com/login?redirect=' + encodeURIComponent(redirectUrl);
// → https://auth.example.com/login?redirect=https%3A%2F%2Fexample.com%2Fcallback%3Ftoken%3Dabc

URLSearchParams を使う方法

クエリパラメータの組み立てには URLSearchParams を使うと、エンコードの手間を省ける。

const params = new URLSearchParams();
params.set('q', '東京タワー&スカイツリー');
params.set('page', '1');
params.set('redirect', 'https://example.com/callback?token=abc');

const url = 'https://example.com/search?' + params.toString();
console.log(url);
// → https://example.com/search?q=%E6%9D%B1%E4%BA%AC...&page=1&redirect=https%3A%2F%2F...

URLSearchParams は値を自動的にエンコードしてくれるため、encodeURIComponent を手動で呼ぶ必要がない。キーと値のペアを扱うなら、こちらを使うほうがミスが少なくなる。

手動で encodeURIComponent

柔軟性が高いが、エンコード忘れのリスクがある。URL の各部品を自分で組み立てる必要がある。

URLSearchParams

クエリパラメータの組み立てに特化しており、エンコードを自動で行う。ただしパス部分には使えない。

デコードの対応関係

エンコードした文字列を元に戻すには、対応するデコード関数を使う。

エンコードデコード対象
encodeURIdecodeURIURL 全体
encodeURIComponentdecodeURIComponentURL の部品
const encoded = '%E6%9D%B1%E4%BA%AC%E3%82%BF%E3%83%AF%E3%83%BC';

console.log(decodeURIComponent(encoded));
// → 東京タワー

// 不正なパーセントエンコーディングをデコードするとエラー
try {
    decodeURIComponent('%E6%9D');
} catch (e) {
    console.log(e.message);
    // → URI malformed
}

decodeURIComponent に不完全なバイト列を渡すと URIError が発生する。外部から受け取った文字列をデコードするときは try-catch で囲んでおくのが安全だ。

まとめの判断基準

ユーザーが入力した検索キーワードを URL のクエリパラメータに埋め込むとき、最も適切な方法はどれですか?

  • encodeURI(keyword) を使う
  • encodeURIComponent(keyword) を使う
  • keyword をそのまま文字列結合する
  • escape(keyword) を使う
__RESULT__

ユーザー入力には & や = などの予約文字が含まれる可能性があるため、encodeURIComponent でエンコードする必要があります。encodeURI は予約文字をエンコードしないため不適切です。escape は非推奨関数であり、UTF-8 を正しく扱えません。

判断は単純で、URL 全体を扱うなら encodeURI、URL の部品を扱うなら encodeURIComponent を使えばよい。迷ったら encodeURIComponent を選ぶほうが安全だ。実際の開発では URLSearchParams を使ってクエリパラメータを組み立てるのが最もミスの少ないアプローチになる。