3秒でわかる
URL の ? 以降に key=value の形で付ける追加情報。検索条件やページ番号など、同じ資源の見せ方を変える指定に使います。
もう少し詳しく
どういうものか
クエリパラメータは、URL の末尾に ? を挟んで付ける key=value 形式の情報です。複数指定するときは & でつなぎます。
https://example.com/products?category=coffee&page=2&sort=price_desc
^ここから先がクエリ文字列サーバー側では、Express なら req.query、Python の Flask なら request.args から辞書として受け取れます。ブラウザの JavaScript からは URLSearchParams で読み書きできます。
なぜ必要か
一覧画面の状態を URL に載せられることが最大の利点です。絞り込みや並び順を画面内の変数だけで持っていると、その状態を共有できず、再読み込みで消え、ブラウザの戻るボタンも効きません。クエリパラメータに載せておけば、URL を貼るだけで同じ表示を相手に見せられ、ブックマークもできます。
パスとの使い分けは、対象そのものか、対象の見せ方かで決まります。ID 3 番の商品はパスで /products/3、商品一覧の 2 ページ目はクエリで /products?page=2 です。
具体例
// サーバー側 (Express)
app.get("/products", (req, res) => {
const page = Number(req.query.page ?? 1);
const category = req.query.category; // 未指定なら undefined
const tags = [].concat(req.query.tag ?? []); // ?tag=a&tag=b は<a href="/glossary/array" class="text-primary font-medium underline underline-offset-2 hover:text-primary-dark">配列</a>になる
let list = products;
if (category) list = list.filter((p) => p.category === category);
res.json(list.slice((page - 1) * 20, page * 20));
});// クライアント側
const params = new URLSearchParams({ category: "コーヒー豆", page: "2" });
const res = await <a href="/glossary/fetch-api" class="text-primary font-medium underline underline-offset-2 hover:text-primary-dark">fetch</a>(`/products?${params}`);URLSearchParams を使うと、日本語や記号のパーセントエンコードを自分で書かずに済みます。
つまずきやすいところ
値は必ず文字列で届きます。req.query.page は "2" なので、page - 1 は動いても page + 1 は "21" になります。数値として使うなら明示的に変換します。
同じキーを複数回書くと、実装によって文字列になったり配列になったりします。Express では 1 個なら文字列、2 個以上なら配列です。片方しか想定していないコードは、条件によって突然壊れます。
エンコードの漏れも頻出です。値に & や空白、日本語が含まれる場合、そのまま連結すると区切りが壊れます。手で文字列を組み立てず、URLSearchParams に任せます。
秘密情報をクエリに載せるのも避けます。URL はアクセスログ、ブラウザ履歴、Referer ヘッダに残るため、トークンやパスワードは本文かヘッダで送ります。
似た用語との違い
| 場所 | 例 | 用途 |
|---|---|---|
| パスパラメータ | /users/42 | どの資源か |
| クエリパラメータ | /users?page=2 | 絞り込み・並び順・ページ |
| フラグメント | /docs#install | ページ内の位置。サーバーへ送られない |
覚え方
? から先は「同じ資源をどう見せるか」の指定です。資源そのものが変わるならパスに置きます。