AWS Amplify Hosting で取れるリクエストヘッダー一覧 (Geo / ASN / デバイス情報)
2026-05-22 14:08 (23 days ago)
結論
AWS Amplify Hosting の SSR でリクエストハンドラに届くヘッダーには、CloudFront が付与する多くのユーザー情報が含まれている。
MaxMind や geoip-lite 等を導入しなくても、国名・都道府県・市区町村・郵便番号・緯度経度・ASN・デバイス種別 がそのまま取れる。
実際に届くヘッダー全部
本番デプロイで request.headers を全部ダンプしたところ、以下が確認できた:
Geo (位置情報) 系
| ヘッダー名 | 値の例 | 意味 |
|---|---|---|
cloudfront-viewer-country |
JP |
ISO 3166-1 alpha-2 国コード |
cloudfront-viewer-country-name |
Japan |
国名 (英語) |
cloudfront-viewer-country-region |
13 |
ISO 3166-2 サブコード (東京都) |
cloudfront-viewer-country-region-name |
Tokyo |
都道府県/州名 |
cloudfront-viewer-city |
Matsubara |
市区町村名 |
cloudfront-viewer-postal-code |
156-0041 |
郵便番号 |
cloudfront-viewer-latitude |
35.xxxxxx |
緯度 |
cloudfront-viewer-longitude |
139.xxxxxx |
経度 |
cloudfront-viewer-time-zone |
Asia/Tokyo |
タイムゾーン |
「郵便番号」「緯度経度」まで来る。プライバシー的に取り扱い注意。
市町村名は実際に私がアクセスしていた市町村名では無く、3Km程度離れていた。
ネットワーク系
| ヘッダー名 | 値の例 | 意味 |
|---|---|---|
cloudfront-viewer-asn |
25XX |
AS 番号 |
cloudfront-viewer-address |
203.0.xxx.xxx:53xxx |
クライアント IP + ポート |
cloudfront-viewer-tls |
TLSv1.3:TLS_AES_128_GCM_SHA256:connectionReused |
TLS バージョン + 暗号スイート |
cloudfront-viewer-http-version |
3.0 |
HTTP のバージョン |
cloudfront-forwarded-proto |
https |
クライアント側のプロトコル |
x-forwarded-for |
203.0.xxx.xxx, 64.252.xxx.xxx |
プロキシ経路上の IP リスト |
x-forwarded-host |
example.com |
クライアント側 Host |
x-forwarded-port |
443 |
クライアント側ポート |
x-forwarded-proto |
https |
クライアント側プロトコル |
via |
3.0 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.cloudfront.net (CloudFront) |
CloudFront 経由情報 |
情報は一部匿名化しています。
ASN まで取れるのは美味しい。これがあれば「特定の ISP から来た」「AWS のデータセンターから来た」のような分類ができる。
デバイス種別
| ヘッダー名 | 値の例 |
|---|---|
cloudfront-is-desktop-viewer |
true |
cloudfront-is-mobile-viewer |
false |
cloudfront-is-tablet-viewer |
false |
cloudfront-is-smarttv-viewer |
false |
cloudfront-is-ios-viewer |
false |
cloudfront-is-android-viewer |
false |
UA パースしなくてもデスクトップ/モバイル/タブレット/TV の判定ができる。CloudFront 側が UA を見て判定してくれる方式。
AWS 内部トレース系
| ヘッダー名 | 用途 |
|---|---|
x-amzn-trace-id |
X-Ray 等のトレース ID |
x-amz-cf-id |
CloudFront のリクエスト ID (サポート問い合わせ時に必要) |
元のブラウザ由来 (上書きされていない!)
| ヘッダー名 | 値の例 |
|---|---|
user-agent |
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 ... Chrome/146.0.0.0 ... |
accept-language |
ja,en-US;q=0.9,en;q=0.8 |
host |
example.com |
過去 (2022 年頃) には「Amplify SSR は user-agent を Amazon CloudFront に置換する」という GitHub issue (#2161) もあったが、現在は元のブラウザ UA が保持されている。ua-parser-js 等で詳細を抽出できる。
SvelteKit SSR での取得方法
load 関数や actions ハンドラの引数に渡ってくる request: Request の headers から普通に取れる。
例: load 関数
// src/routes/+page.server.ts
import type { PageServerLoad } from './$types';
export const load: PageServerLoad = async ({ request }) => {
const headers = request.headers;
const country = headers.get('cloudfront-viewer-country-name'); // 'Japan'
const region = headers.get('cloudfront-viewer-country-region-name'); // 'Tokyo'
const asn = headers.get('cloudfront-viewer-asn'); // '25XX'
return {
location: { country, region, asn }
};
};
例: action ハンドラ
// src/routes/+page.server.ts
import type { Actions } from './$types';
export const actions: Actions = {
default: async ({ request }) => {
const country = request.headers.get('cloudfront-viewer-country');
// ...
}
};
例: API endpoint (+server.ts)
// src/routes/api/some/+server.ts
import type { RequestHandler } from './$types';
export const GET: RequestHandler = async ({ request }) => {
const country = request.headers.get('cloudfront-viewer-country');
return new Response(JSON.stringify({ country }));
};
ユーティリティとしてまとめる
実プロジェクトでは、抽出ロジックをユーティリティ関数にまとめると扱いやすい。
// src/lib/server/geo.ts
export type DeviceType = 'desktop' | 'mobile' | 'tablet' | 'tv' | undefined;
export interface GeoInfo {
country?: string;
countryCode?: string;
region?: string;
asn?: number;
deviceType?: DeviceType;
}
export function extractGeoInfo(headers: Headers): GeoInfo {
const asnRaw = headers.get('cloudfront-viewer-asn');
const asn = asnRaw ? parseInt(asnRaw, 10) : undefined;
let deviceType: DeviceType;
if (headers.get('cloudfront-is-tablet-viewer') === 'true') {
deviceType = 'tablet';
} else if (headers.get('cloudfront-is-mobile-viewer') === 'true') {
deviceType = 'mobile';
} else if (headers.get('cloudfront-is-smarttv-viewer') === 'true') {
deviceType = 'tv';
} else if (headers.get('cloudfront-is-desktop-viewer') === 'true') {
deviceType = 'desktop';
}
return {
country: headers.get('cloudfront-viewer-country-name') || undefined,
countryCode: headers.get('cloudfront-viewer-country') || undefined,
region: headers.get('cloudfront-viewer-country-region-name') || undefined,
asn: asn !== undefined && Number.isFinite(asn) ? asn : undefined,
deviceType
};
}
呼び出し側:
import { extractGeoInfo } from '$lib/server/geo';
export const load: PageServerLoad = async ({ request }) => {
const geo = extractGeoInfo(request.headers);
console.log(geo);
// { country: 'Japan', countryCode: 'JP', region: 'Tokyo', asn: 25XX, deviceType: 'desktop' }
};
参考
評価をお願いします (会員登録・ログイン不要)
現在の評価: 5.0 (1)
著者は、アプリケーション開発会社 Cyberneura を運営しています。
開発相談をお待ちしています。
開発相談をお待ちしています。