フォームのHTMLに type="hidden" があるのに、ブラウザーには入力欄が見当たらない。何のために置かれているのか、送信すると何が起こるのか、迷うことはありませんか。
hidden inputは、画面に入力欄を出さず、記事IDなどの値をフォームと一緒に送る部品です。ただし、値を秘密にしたり、書き換えを防いだりする機能はありません。
form と input を見たことがある方に向けて、まず name と value の組み合わせを読み、送信される条件と受信側の注意点を整理します。読み終えたら、画面に見えない値を予想し、ブラウザーの開発者ツールで確認する場所が分かります。
- hidden inputの役割と、安全に扱うための注意点
name・valueから、どのような値が送信されるか- DevToolsのNetworkで送信値を確かめる手順
hidden inputとは?
hidden inputは、利用者に入力してもらう必要はないものの、フォームの処理には必要な値を送るためのinput要素です。基本形は次のとおりです。
<input type="hidden" name="article_id" value="42" />
この要素は通常、ページ上に入力欄として表示されません。しかし、フォームを送信すると、nameとvalueが次の組み合わせになります。
article_id=42
画面に表示されないことと、フォームで送信されないことは別です。

この図では、入力欄の title=HTMLフォーム入門 と、hidden inputの article_id=42 が一緒に送られます。入力欄が画面にあるかどうかで、送信対象が決まるわけではありません。
フォームで使う3つの用語
- フォームコントロール:
inputやbuttonなど、フォームを構成する部品 - フォームデータ:送信時に組み立てられる
name=valueの組み合わせ - サーバー:送られたデータを受け取り、保存や更新などの処理を行う側
hidden inputは、秘密の値を隠して保管する場所ではありません。 画面へ入力欄を出す必要がないデータを、フォームの一部として送るために使います。
type="hidden"の基本的な書き方
hidden inputでは、type、name、valueの3つをセットで確認すると理解しやすくなります。
この例の/articles/updateは説明用の送信先です。HTMLだけでは保存・更新処理はできません。 実際の保存・更新には、送信先で動くサーバー側のプログラムが必要です。
<form action="/articles/update" method="post">
<input type="hidden" name="article_id" value="42" />
<label for="title">記事タイトル</label>
<input id="title" name="title" type="text" />
<button type="submit">更新する</button>
</form>
type:入力欄の種類
type属性へhiddenを指定すると、そのinputはhidden状態になります。利用者がクリックして入力する欄ではなく、キーボードフォーカスも受け取りません。
name:送信する項目名
name="article_id"は、送信先が値を見分けるための項目名です。送信結果ではarticle_id=42の左側になります。一方、idはJavaScriptやlabelなどから要素を識別するための属性で、フォーム送信の項目名にはなりません。送信にはnameを使います。
value:送信する値
value="42" は送信する値を指定しています。JavaScriptなどで送信前に変更した場合は、フォームの送信データが作られる時点の現在値が送られます。
たとえば、現在値が57へ変わっていれば、送信される組み合わせは次のようになります。
article_id=57
GET・POSTでの値の置き場所
通常のHTMLフォーム送信では、hidden inputも他の入力欄と同じフォームデータです。GETではURLの ? より後のクエリー文字列へ、POSTではブラウザーからサーバーへ送るHTTPリクエストの本文へ入ります。
<form action="/preview" method="get">
<input type="hidden" name="article_id" value="42" />
<button type="submit">プレビューする</button>
</form>
このフォームを説明用ドメイン example.com に置いた場合、GETで送るURLは次の形になります。/preview は例示用の送信先で、結果を表示するには受信側の処理が必要です。
https://example.com/preview?article_id=42
GETとPOSTの選び方を先に整理したい場合は、HTMLフォームのGET・POSTの違いも参考にしてください。
type="hidden"・hidden属性・CSSの違い
名前が似ていますが、type="hidden"とグローバル属性のhiddenは目的が異なります。パスワード入力欄やCSSによる非表示とも区別しましょう。
| 書き方 | 主な目的 | フォーム送信との関係 |
|---|---|---|
<input type="hidden"> | 画面に出さないフォーム値を持つ | nameがあり無効化されていなければ送信対象 |
<div hidden> | 今は関連しない要素などを表示しない | それ自体はフォーム値を作らない |
display: none | CSSで要素を描画しない | フォーム部品なら非表示だけを理由に送信対象から外れない |
<input type="password"> | 入力中の文字を画面上で隠す | 利用者が入力する欄であり、hidden inputではない |
より詳しい仕様は、MDNのhidden inputリファレンスでも確認できます。
hidden inputの主な使い方
hidden inputは、画面で入力し直す必要がない「処理の文脈」を送る用途に向いています。ただし、送られた値をそのまま信用するのではなく、用途ごとにサーバー側の確認が必要です。
編集対象のレコードID
レコードIDとは、記事や注文などを1件ずつ区別するための番号や文字列です。記事の編集フォームでは、どの記事を更新するのかを伝えるためにIDを入れることがあります。
<input type="hidden" name="article_id" value="42" />
サーバーは42が数字かを確認するだけでなく、ログイン中の利用者が記事42を編集できるかを確認します。値の形式を確認することと、操作してよい権限を確認することは別です。
ログイン中かを確かめるのが「認証」、ログイン中の利用者が記事42を編集してよいか確かめるのが「認可」です。
送信後の戻り先・表示状態
一覧から編集画面へ移動したときに、送信後の戻り先やタブ名を引き継ぐ例です。
<input type="hidden" name="return_to" value="/articles?page=2" />
戻り先を受け取る場合も、外部サイトなど任意のURLへ無条件に転送しないよう、サーバー側で許可したパスかを確認します。
CSRFトークンの受け渡し
ログイン中の利用者に意図しない操作をさせるCSRF攻撃への対策として、サーバーが生成したトークンをhidden inputへ入れる方法があります。
<input type="hidden" name="csrf_token" value="{{ csrf_token }}" />
{{ csrf_token }} は、サーバー側のテンプレートが実際のトークンへ置き換えることを表す説明用の記号です。普通のHTMLファイルへ貼るだけでは置き換わりません。固定した文字列を本番のトークンとして使わないでください。
CSRFトークンはサーバーが生成し、受信時に照合して初めて意味を持ちます。
詳しい設計では、利用しているフレームワークの公式機能と、OWASPのCSRF対策ガイドを確認してください。
hidden inputの安全上の注意点
hidden inputのHTMLはブラウザーへ届きます。利用者はDevToolsで要素を調べ、valueを書き換えてからフォームを送ることができます。JavaScriptからの変更も可能です。
hidden inputの値は、DevToolsなどで見たり書き換えたりできます。

hidden inputは値を運ぶ仕組みであり、その値を信用してよいかはサーバーが決めます。 通常の入力欄、URLの値、JavaScriptで作った値も含め、ブラウザーから届く値はすべて検証対象です。
hidden inputへ入れる値の注意点
次のような重要な判断を、hidden inputの値だけで行わないでください。
- 商品の販売価格や注文合計
- 管理者・一般利用者などの権限
- 操作対象の所有者や本人確認
- 割引率、在庫数、決済結果
- パスワード、APIキー、秘密鍵など、ブラウザーへ渡してはいけない秘密情報
CSRFトークンは正規の画面へ渡し、サーバーで照合するための値です。一方、APIキーや秘密鍵など、利用者のブラウザーへ渡してはいけない秘密情報はhidden inputへ入れません。
たとえば、次のコードで価格を送っても、利用者は1000を1へ変更できます。
<!-- この値だけを信用して請求額を決めてはいけない -->
<input type="hidden" name="price" value="1000" />
サーバーは商品IDを基に正しい価格を取得し直し、在庫や割引条件もサーバー側の情報から計算します。
サーバー側で確認する4つの観点
- 形式:数値か、長さや文字種は適切か
- 業務ルール:存在するIDか、現在も操作可能な状態か
- 認可:ログイン中の利用者が対象を操作してよいか
- リクエストの正当性:CSRFトークンなどが正しく照合できるか
HTMLのrequiredやpatternは、hidden状態には適用されず、そもそもブラウザー側の検証だけで安全性を保証できません。最終判断はサーバー側で行います。
hidden inputで送信される値・送信されない値
「画面に見えないから送られなかった」と考える前に、name、無効化の状態、フォームとの関連付け、送信直前の値を確認しましょう。次の表は、送信するフォームに関連付けられたhidden inputを、通常のHTMLフォームで送る場合です。
| 状態 | 送信結果 | 確認すること |
|---|---|---|
name="article_id" value="42" | article_id=42 | 通常の送信対象 |
nameがない、または空 | 項目として送信されない | 受信側と同じnameを付ける |
disabledが付いている | 送信されない | 無効化する必要があるか見直す |
valueが空、または省略 | article_id= のように空の値を送信 | nameがあり、無効でない場合。空値と項目の欠落を区別する |
同じnameが複数ある | 同じ項目名で複数の値が送られる | サーバー側の受け取り方を確認する |
| JavaScriptで値を変更 | 変更後の現在値が送られる | 送信直前のDOMを確認する |
nameがない、またはdisabledのhidden inputは送信されません。
nameがない例
<!-- 値は入っていても、項目名がないため送信されない -->
<input type="hidden" value="42" />
この例ではnameがないため、value="42"があっても項目として送信されません。
disabledが付いている例
<!-- disabledのフォームコントロールは送信されない -->
<input type="hidden" name="article_id" value="42" disabled />
input自身に disabled がなくても、親の <fieldset disabled> によって無効になる場合があります。親要素も確認してください。なお、disabled="false" も属性が存在するため無効です。有効にするには属性を外します。
フォームの外に置く場合
hidden inputをform要素の外へ置くだけでは、そのフォームのデータになりません。通常はフォームの内側へ置くのが分かりやすい方法です。
外側へ置く必要がある場合は、フォームのidとinputのform属性を一致させます。
<form id="edit-form" action="/articles/update" method="post">
<button type="submit">更新する</button>
</form>
<input
type="hidden"
name="article_id"
value="42"
form="edit-form"
/>
hidden inputを含むフォームの実例
次は、記事ID・CSRFトークン・記事タイトルを送るコード例です。/articles/update に更新処理があり、サーバーが生成したトークンをテンプレートへ渡す想定です。このHTMLだけで記事を保存できる完成アプリではありません。
<form action="/articles/update" method="post">
<input type="hidden" name="article_id" value="42" />
<input type="hidden" name="csrf_token" value="{{ csrf_token }}" />
<label for="title">記事タイトル</label>
<input
id="title"
name="title"
type="text"
value="HTMLフォーム入門"
required
/>
<button type="submit">更新する</button>
</form>
送信項目と値の読み取り練習
サーバーがトークンを埋め込み、タイトルを変更せずに送信する場合を考えます。コードの name と value を読み、送信される3組を予想してみてください。
予想できたら、次の答えを確認しましょう。
article_id=42
csrf_token=サーバーが生成した実際の値
title=HTMLフォーム入門
buttonにはnameがないため、この例ではボタンの値は送信項目になりません。サーバーは受け取った記事ID・トークン・タイトルを確認し、認可と検証に通ったときだけ更新します。
formのactionとmethodを含めて復習したい場合は、HTMLフォームのaction・method属性を確認してください。nameとvalueの基本は、HTMLのinput属性の解説で詳しく紹介しています。
DevToolsでhidden inputの送信値を確認する方法
実際に送信した内容は、PC版Chromeの開発者ツール(DevTools)にある Network(ネットワーク)で確認できます。自分が管理する検証用フォームと受信先を使ってください。説明用の /articles/update をそのまま指定しても、受信・保存処理は用意されません。
Networkで送信値を確かめる手順
- Networkを開く:フォームのページを開き、Windows/Linuxは
Ctrl+Shift+I、MacはCommand+Option+IでDevToolsを表示します。Networkを選び、送信前にPreserve log(ログを保持)を有効にします。 - フォームを送信する:必要な値を入力し、送信ボタンを押します。Networkに新しいリクエストが現れたことを確認します。必須欄のエラーで送信が止まった場合は、その欄を修正します。
- 送信先のリクエストを選ぶ:一覧から
actionに対応する行を選びます。Headers(ヘッダー)のRequest URLとRequest Methodが、意図した送信先・GET/POSTかを確認します。転送後のページと取り違えないようにします。 - 送信値と結果を確認する:
Payload(ペイロード)を開き、GETはQuery String Parameters、通常のPOSTフォームはForm Dataを見ます。article_id=42など、予想した項目名と現在値が一致していれば送信内容の確認は完了です。保存を伴う場合は、応答と保存後の画面も確かめます。
表示名はChromeの言語設定で異なります。JavaScriptがJSONなど独自の形式で送信している場合は、通常のフォームとは表示が異なるため、その実装に合わせて確認します。
送信内容と保存結果を混同しないため、次の3点を確認します。Networkに値があることだけでは、サーバーで受理・保存されたとは判断できません。
- 期待した項目名があるか
- 値が送信直前の内容になっているか
- GETのURLかPOSTの本文か、意図した場所に入っているか
Chrome DevToolsの詳しい機能は、Chrome公式のNetworkリファレンスで確認できます。
hidden inputが送信されない・期待どおり動かないとき
うまくいかないときは、ブラウザー側とサーバー側を分けて確認します。
Networkに項目があっても、サーバー側で受理・保存されたとは限りません。
| 症状 | 主な原因 | 確認・対処 |
|---|---|---|
| 項目そのものがない | nameがない・空 | 受信側と一致するnameを付ける |
| 項目が送られない | disabledが付いている | 不要ならdisabledを外す |
| 別のフォームで送られる | フォーム外・関連付け違い | 内側へ置くかform属性を合わせる |
| 値が想定と違う | JavaScriptが書き換えた | ElementsとNetworkで現在値を比較する |
| Networkにはあるが処理されない | 受信側の項目名や処理が違う | サーバーの仕様・ログ・検証結果を確認する |
| 他人のデータを操作できる | 認可確認が不足 | 所有者・権限をサーバー側で必ず照合する |
まずNetworkに項目があるかを確認し、なければHTMLとフォームの関連付け、あればサーバー側の受け取り方を調べると原因を切り分けやすくなります。
よくある質問
- hidden inputの値は利用者に見えますか?
-
通常のページ表示では入力欄として見えません。ページソースでは受け取ったHTMLを確認でき、DevToolsのElementsでは現在の要素と値を調べて変更できます。実際の送信値はNetworkのPayloadで確認します。秘密にしたい値は入れないでください。
- hidden inputの値は利用者が変更できますか?
-
はい。DevToolsやJavaScriptから変更できます。サーバーは、変更される可能性がある値として形式、業務ルール、認可を確認します。
- GETフォームでもhidden inputを使えますか?
-
使えます。
name=valueはURLのクエリー文字列へ入ります。URL、履歴、ログなどへ残り得るため、機微情報や秘密のトークンをGETで送らないでください。 type="password"と同じですか?-
異なります。passwordは利用者が文字を入力する表示上の入力欄で、入力文字を伏せます。hidden inputは入力欄そのものを表示せず、あらかじめ用意したフォーム値を持ちます。どちらも送信値そのものを安全に暗号化する機能ではありません。
- hidden inputに
labelやidは必要ですか? -
hidden inputは
labelの関連付け対象ではありません。idも送信には不要ですが、JavaScriptから特定するなどの目的があれば付けられます。送信項目名にはnameを使います。 - JavaScriptでhidden inputの値を変更できますか?
-
変更できます。ただし、hidden状態では
inputイベントやchangeイベントが通常の入力欄のようには発生しません。変更後の値を使う処理は、値を設定したコードの流れで明示的に扱いましょう。 - hidden inputへCSRFトークンを入れるだけで安全ですか?
-
いいえ。サーバーが予測困難なトークンを生成し、フォームへ埋め込み、受信時にセッション等と照合し、欠落や不一致を拒否する一連の仕組みが必要です。利用するフレームワークのCSRF保護機能を優先してください。
_charset_というnameには特別な意味がありますか?-
発展的な仕様として、hidden inputの
nameを_charset_にすると、送信時に値が文字エンコーディング名へ置き換わる特別な挙動があります。通常の初心者向けフォームで自分から使う場面は多くありません。
まとめ
hidden inputは、画面に入力欄を表示せず、フォーム処理に必要な値をname=valueとして送るための部品です。
- 基本形は
<input type="hidden" name="項目名" value="値"> nameがない場合やdisabledの場合は送信されない- GETではURL、POSTではリクエスト本文へ値が入る
- レコードID、戻り先、CSRFトークンなどに使える
- 値はDevToolsやJavaScriptで確認・変更できる
- サーバー側で形式、業務ルール、認可、トークンを確認する
まずは実例の name=value を読み取ってみましょう。検証用の受信先を用意できたら、Networkで予想と実際の送信値を照合します。「画面に見えない」と「信用できる」を分けて考えることが、hidden inputを扱う基本です。

