2026年9月24日
2026年9月24日
IDN(日本語ドメイン)をPunycodeに変換する手順と注意点
日本語ドメインなどの IDN(国際化ドメイン名)は、DNS やサーバー設定の中では xn-- で始まる Punycode(ASCII 形式)に変換して扱います。変換自体はコマンド1行でできますが、変換規格の違いや、どの設定に Punycode を書くべきかを知らないと、名前解決や証明書でつまずきます。この記事では、変換の方法と、WordPress サイトを IDN で運用するときに Punycode で書くべき場所を整理します。
IDN と Punycode の関係
DNS はもともと英数字とハイフンしか扱えません。そこで、日本語.jp のような名前は、ラベル(ドットで区切られた各部分)ごとに Punycode という方式で ASCII に変換し、先頭に xn-- を付けて扱います。
- 表示用の形(U-label):
日本語.jp - DNS 上の形(A-label):
xn--wgv71a119e.jp
ブラウザはアドレスバーで日本語の形を表示しますが、実際の通信では A-label を使っています。サーバーや DNS の設定ファイル、証明書の中身はすべて A-label です。
変換の前に知っておきたい規格の違い
IDN の変換規則には、古い IDNA2003 と、現在の IDNA2008、それに互換処理を定めた UTS #46 があります。ほとんどの日本語ドメインはどれで変換しても同じ結果になりますが、次のような点で差が出ます。
- 大文字・全角英数字: UTS #46 は小文字・半角へ正規化してから変換します。IDNA2008 の厳密な処理ではエラーになります
- 一部の文字の扱い: ドイツ語の
ßなどは、IDNA2003 ではssに置き換えられ、IDNA2008 ではそのまま1文字として変換されます。同じ入力から別のドメインが出てくるため、ツールによって結果が食い違う原因になります
現在の主要なブラウザや多くのライブラリは、UTS #46 の非移行(nontransitional)処理を採用しています。迷ったら「UTS #46 の nontransitional」で変換できるツールを使うと、ブラウザと同じ結果になりやすいです。
コマンドラインで変換する
idn2(Linux)
libidn2 に含まれる idn2 コマンドが手軽です。ディストリビューションによってはパッケージ名が idn2 や libidn2 です。
idn2 日本語.jp
# xn--wgv71a119e.jp
idn2 -d xn--wgv71a119e.jp
# 日本語.jp
-d で逆方向(A-label から日本語)に戻せます。ターミナルの文字コードが UTF-8 でないと、入力の段階で文字化けして別の結果が出ることがあるため、locale で UTF-8 になっているかを確認しておきます。
Python
Python の標準の idna コーデックは IDNA2003 準拠です。現行の規則で変換したい場合は、外部パッケージの idna を使います。
# 標準ライブラリ(IDNA2003 準拠)
print("日本語.jp".encode("idna")) # b'xn--wgv71a119e.jp'
# pip install idna(IDNA2008 準拠)
import idna
print(idna.encode("日本語.jp")) # b'xn--wgv71a119e.jp'
print(idna.encode("EXAMPLE.jp", uts46=True)) # b'example.jp'
print(idna.decode("xn--wgv71a119e.jp")) # 日本語.jp
全角英字の混じった入力は、uts46=True を付けないとエラーになります。ユーザーが入力したドメインを扱う処理では、このオプションで正規化してから変換するのが安全です。
Node.js
Node.js では、組み込みの url モジュールで変換できます。かつて使われていた punycode モジュールは非推奨になっているため(2026年10月現在)、新しく書くコードでは使わないようにします。
const { domainToASCII, domainToUnicode } = require('node:url');
console.log(domainToASCII('日本語.jp')); // xn--wgv71a119e.jp
console.log(domainToUnicode('xn--wgv71a119e.jp')); // 日本語.jp
console.log(new URL('https://日本語.jp/').hostname); // xn--wgv71a119e.jp
PHP
PHP では intl 拡張の idn_to_ascii() と idn_to_utf8() を使います。intl が入っていない環境では関数が存在しないため、php -m | grep intl で確認してください。
<?php
$ascii = idn_to_ascii( '日本語.jp', IDNA_NONTRANSITIONAL_TO_ASCII, INTL_IDNA_VARIANT_UTS46 );
$utf8 = idn_to_utf8( 'xn--wgv71a119e.jp', IDNA_NONTRANSITIONAL_TO_UNICODE, INTL_IDNA_VARIANT_UTS46 );
if ( false === $ascii ) {
// 変換できない文字が含まれている
}
変換に失敗すると false が返るため、結果をそのまま使わずに確認します。第3引数の変換方式は UTS #46 を明示しておくと、PHP のバージョン差に左右されません。
WordPress で Punycode を書くべき場所
日本語ドメインで WordPress を運用する場合、設定値は基本的に A-label で統一します。混在させると、リダイレクトのループや、同じページが2つの URL で存在する状態になりやすいからです。
WordPress のアドレス設定
管理画面の「設定」→「一般」にある WordPress アドレスとサイトアドレスには、https://xn--wgv71a119e.jp の形で入れます。WP-CLI で確認・変更する場合は次のとおりです。変更前にデータベースのバックアップを取っておきます。
wp option get home
wp option get siteurl
wp option update home 'https://xn--wgv71a119e.jp'
wp option update siteurl 'https://xn--wgv71a119e.jp'
すでに日本語の形で URL が保存されている投稿や設定がある場合は、wp search-replace を --dry-run 付きで実行して、件数を確認してから置換します。
Web サーバーと証明書
- Apache の
ServerName、Nginx のserver_nameには A-label を書きます - DNS ゾーンのレコード名も A-label です。管理画面によっては日本語入力を自動で変換してくれますが、保存後の表示を確認します
- SSL 証明書の申請(certbot の
-dなど)にも A-label を指定します。証明書の SAN には A-label が記録されます
メールアドレス
日本語ドメインを使ったメールアドレス(ローカル部は英字、ドメイン部が日本語)は、WordPress やプラグインの入力チェックで弾かれることがあります。会員登録やフォームでメールアドレスを受け付ける場合は、ドメイン部を A-label に変換した形で登録してもらうか、テスト環境で実際に通るかを事前に確かめておきます。
変換時によくあるつまずき
- ラベル単位で変換していない:
xn--はドットで区切った日本語部分ごとに付きます。www.日本語.jpならwww.xn--wgv71a119e.jpになり、wwwやTLDはそのままです - 見た目が同じ別の文字: キリル文字の「а」とラテン文字の「a」のように、見た目が似た別の文字で作られたドメインは、変換すると別の A-label になります。フィッシング対策で、ブラウザが日本語ではなく
xn--の形のまま表示することもあります - 長さの上限: 1ラベルは A-label の状態で63文字までです。日本語の文字数が少なくても、変換後に上限を超えて登録できないことがあります
- 検索エンジン上の表示: Google 検索などでは日本語の形で表示されることが多いですが、Search Console のプロパティ登録などでは A-label を求められる場面もあります
まとめ
- IDN は DNS・サーバー設定・証明書の中では
xn--で始まる A-label で扱う - 変換規格には IDNA2003・IDNA2008・UTS #46 があり、迷ったら UTS #46 の nontransitional で変換する
- Python 標準の
idnaコーデックは IDNA2003 準拠なので、現行規則が必要ならidnaパッケージを使う - WordPress の home・siteurl、Web サーバーの設定、証明書は A-label で統一する
- 変換後の長さや、見た目が似た別の文字には注意する