17NAS DEVELOPER API

IP検索 API

1 リクエストで、アクセス元の実 IP、IPv4 か IPv6 か、国・地域、ASN、通信事業者、タイムゾーンをまとめて取得できます。

17nas.com のIPv6 判定ツール自体がこのエッジ上で動いています。これまでに 181,053 回の判定を処理してきましたが、そのすべてがこの API と同じ経路を通っています。

エンドポイント
ipapi.17nas.com
認証方式
Bearer API Key
出力形式
JSON / Text
curl
curl https://ipapi.17nas.com/v1/ip \
  -H "Authorization: Bearer 17nas_live_xxx"
{
  "ip": "203.0.113.10",
  "protocol": "IPv4",
  "country": { "code": "CN" },
  "asn": { "number": 4134 },
  "edge": { "colo": "HKG" }
}
累計判定回数
181,053 回
ユニーク IP
47,088 件
直近 30 日
24,374 回
配信ノード
グローバルエッジ
LIVE DEMO

登録不要。まず動くところを確認

クリックすると、今つながっているネットワークの実 IP で公開エンドポイントを 1 回呼び出し、加工なしのレスポンスをそのまま表示します。ここで叩いているのは公開エンドポイントで、フィールド構成は API キー付きの /v1/ip とは異なります。後者は下のドキュメントが正です。

GET https://ip.17nas.com?format=json
上のボタンを押すと、実際のレスポンスがここに表示されます。
今叩いたのは公開エンドポイントです。単発の確認や手動の切り分けには十分です。

自分のサイト・アプリ・ミニプログラム・サーバーサイドのスクリプトに組み込む段階になると、API キーが必要です。公開エンドポイントには専用クォータも、利用統計も、エラーログも、IP 許可リストもありません。悪用によっていつ絞られてもおかしくなく、障害時に確認できるログも残りません。

月 1,000 回の無料開発枠を受け取る
USE CASES

みんな何に使っているか

以下のコードはそのままコピーして動きます。17nas_live_xxx を自分のキーに置き換えるだけです。

家庭回線の IP が変わったら DDNS を更新

家庭回線のグローバル IP はいつ変わってもおかしくなく、変わると NAS のドメインは存在しないアドレスを指したままになります。cron で 5 分ごとに確認し、変わったときだけ DNS 事業者の API を呼びます。毎回更新するより手間がかからず、DNS 側のクォータも無駄に使いません。

ddns-update.sh
#!/bin/bash
# crontab: */5 * * * * /opt/ddns-update.sh
KEY="17nas_live_xxx"
CACHE="/tmp/.last_wan_ip"

IP=$(curl -fsS --max-time 10 "https://ipapi.17nas.com/v1/ip?format=text" \
      -H "Authorization: Bearer $KEY") || exit 0

# 取得できない、または前回と同じなら終了。DNS 事業者を叩かない
[ -z "$IP" ] && exit 0
[ "$IP" = "$(cat "$CACHE" 2>/dev/null)" ] && exit 0

echo "$IP" > "$CACHE"
logger -t ddns "WAN IP changed to $IP"

# 自分が使っている DNS 事業者の API に置き換える
curl -fsS -X POST "https://dns.example.com/api/record" \
  -d "name=nas.example.com&type=A&value=$IP"

グローバル IP が変わったら通知

DNS を自動で書き換えるのは怖いが、IP がいつ変わったかは知りたい。変わった瞬間に通知を飛ばし、通信事業者と地域も一緒に知らせます。事業者がアドレスプールを入れ替えたときに特に役立ちます。

wan_watch.py
import json, pathlib, requests

KEY = "17nas_live_xxx"
PUSH = "https://www.pushplus.plus/send"   # 自分の通知チャネルに置き換える
TOKEN = "your_pushplus_token"
CACHE = pathlib.Path("/var/tmp/wan_ip.json")

r = requests.get(
    "https://ipapi.17nas.com/v1/ip",
    headers={"Authorization": f"Bearer {KEY}"},
    timeout=10,
)
r.raise_for_status()
now = r.json()

# 残りクォータはレスポンスヘッダーに入っている。別途問い合わせ不要
print("今月の残り回数:", r.headers.get("X-Quota-Remaining"))

last = json.loads(CACHE.read_text()) if CACHE.exists() else {}
if last.get("ip") == now["ip"]:
    raise SystemExit(0)

CACHE.write_text(json.dumps(now))
requests.post(PUSH, json={
    "token": TOKEN,
    "title": f"グローバル IP が変わりました:{now['ip']}",
    "content": (
        f"プロトコル {now['protocol']}\n"
        f"通信事業者 {now['asn']['organization']} (AS{now['asn']['number']})\n"
        f"地域 {now.get('city') or '-'} / {now['country']['code']}\n"
        f"以前の IP {last.get('ip', '記録なし')}"
    ),
}, timeout=10)

普段と違う場所からのログインを検知

ログイン時に IP の地域と ASN を記録します。次回のログインが別の地域から、あるいは家庭回線からデータセンターの IP に変わっていたら二要素認証を要求します。IP をそのまま保存するより確実です。家庭回線の IP は毎日変わりますが、地域や通信事業者は変わりません。

login_risk.php
<?php
/** ログイン成功後に呼び出し、二要素認証が必要かどうかを返す */
function login_needs_verify(PDO $pdo, int $userId): bool
{
    $ch = curl_init('https://ipapi.17nas.com/v1/ip');
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT => 5,
        CURLOPT_HTTPHEADER => ['Authorization: Bearer 17nas_live_xxx'],
    ]);
    $body = curl_exec($ch);
    $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    // 判定用 API が落ちてもユーザーを締め出さない。フェイルオープンにする
    if ($status !== 200 || !$body) {
        error_log('ip-api unavailable, skip risk check');
        return false;
    }

    $now = json_decode($body, true);
    $fingerprint = $now['country']['code'] . '|' . $now['region'] . '|' . $now['asn']['number'];

    $stmt = $pdo->prepare('SELECT ip_fingerprint FROM user_login_env WHERE user_id = ?');
    $stmt->execute([$userId]);
    $known = $stmt->fetchColumn();

    $pdo->prepare('REPLACE INTO user_login_env (user_id, ip_fingerprint, updated_at) VALUES (?, ?, NOW())')
        ->execute([$userId, $fingerprint]);

    return $known !== false && $known !== $fingerprint;
}

IPv4 / IPv6 でオリジンを振り分ける

デュアルスタック環境では、IPv6 で入ってきたユーザーに対してバックエンドが IPv4 のみだと、変換の 1 ホップで数十ミリ秒を無駄にします。先にプロトコルを判定し、どのオリジンに向けるか(またはどのリソース URL を返すか)を決めます。

origin-select.js
const KEY = process.env.IP_API_KEY;

async function pickOrigin() {
  const res = await fetch('https://ipapi.17nas.com/v1/ip', {
    headers: { Authorization: `Bearer ${KEY}` },
    signal: AbortSignal.timeout(5000),
  });

  if (res.status === 429) {
    // クォータ切れ、またはレート制限。復帰時刻は X-Quota-Reset を参照
    console.warn('quota/rate limited, reset at', res.headers.get('X-Quota-Reset'));
    return ORIGINS.v4;   // 例外を投げず、デフォルト経路にフォールバック
  }
  if (!res.ok) return ORIGINS.v4;

  const { protocol, edge } = await res.json();
  console.log('edge colo:', edge.colo);
  return protocol === 'IPv6' ? ORIGINS.v6 : ORIGINS.v4;
}

const ORIGINS = {
  v4: 'https://origin-v4.example.com',
  v6: 'https://origin-v6.example.com',
};

アプリ / ミニプログラムの監査ログ保存

アプリやミニプログラムの審査では、ユーザー操作ログの保存が求められ、IP とその地域は必須項目です。重要なのは必ずサーバー側から呼ぶこと。キーをクライアントのパッケージに埋め込むのは、クォータを全ユーザーに配るのと同じです。

audit_log.php
<?php
/**
 * サーバー側でコンプライアンスログを 1 件書き込む。
 * 注意:キーはサーバーにのみ置くこと。アプリ / ミニプログラムは自分のサーバーに
 * リクエストを送り、そのサーバーが 17NAS を呼ぶ。クライアントはキーに触れない。
 */
function write_audit_log(PDO $pdo, int $userId, string $action): void
{
    $ctx = ['ip' => null, 'country' => null, 'isp' => null];

    $ch = curl_init('https://ipapi.17nas.com/v1/ip');
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT => 5,
        CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('IP_API_KEY')],
    ]);
    if ($body = curl_exec($ch)) {
        $data = json_decode($body, true);
        $ctx = [
            'ip' => $data['ip'] ?? null,
            'country' => $data['country']['code'] ?? null,
            'isp' => $data['asn']['organization'] ?? null,
        ];
    }
    curl_close($ch);

    $pdo->prepare(
        'INSERT INTO audit_logs (user_id, action, ip, country, isp, created_at)
         VALUES (?, ?, ?, ?, ?, NOW())'
    )->execute([$userId, $action, $ctx['ip'], $ctx['country'], $ctx['isp']]);
}

複数回線の出口 IP を一括点検

VPS やプロキシ、マルチ回線が並んでいて、各回線の実際の出口 IP と着地拠点を確認したい。順に叩けば、経路がおかしいものはその場で分かります。

egress-check.sh
#!/bin/bash
KEY="17nas_live_xxx"
IFACES=("eth0" "eth1" "wg0")

printf "%-8s %-40s %-10s %s\n" "IF" "出口IP" "プロトコル" "通信事業者"
for IF in "${IFACES[@]}"; do
  JSON=$(curl -fsS --max-time 8 --interface "$IF" \
          "https://ipapi.17nas.com/v1/ip" \
          -H "Authorization: Bearer $KEY" 2>/dev/null)

  if [ -z "$JSON" ]; then
    printf "%-8s %-40s %-10s %s\n" "$IF" "(疎通なし)" "-" "-"
    continue
  fi

  printf "%-8s %-40s %-10s %s\n" \
    "$IF" \
    "$(echo "$JSON" | jq -r .ip)" \
    "$(echo "$JSON" | jq -r .protocol)" \
    "$(echo "$JSON" | jq -r .asn.organization)"
done
COMPARISON

自前で立てるべきか?

実 IP を返すこと自体は難しくありません。難しいのは何年も動かし続けることです。三つの選択肢それぞれのコストを並べます。

比較項目 自前構築 海外サービス 17NAS
中国本土からの遅延自分のサーバー次第越境のため変動が大きい最寄りのエッジが応答
IPv6 対応デュアルスタックを自分で設定ほぼ対応ネイティブ対応
GeoIP / ASN データ更新自分でダウンロードして更新提供側が対応提供側が対応
日々の運用証明書・サーバー・監視をすべて自分でなしなし
利用統計とエラーログ自分で実装ありコンソールに標準搭載
支払い方法—多くはクレジットカードのみAlipay
障害時の問い合わせ先自分英語のチケット、時差あり中国語サポート、同一タイムゾーン
初期コストサーバー 1 台 + 自分の時間従量課金無料で月 1,000 回

公平に言えば、個人の趣味で 1 日数回叩くだけなら、自分の Nginx で $remote_addr を返せば十分で、お金を払う必要はありません。買う価値があるのは「落ちたら誰かに問い詰められる」場面です。本番トラフィック、ログ保存義務、長期間止められない自動処理などです。

PLANS

API 料金プラン

クォータを使い切ると呼び出しが止まるだけです。未払いは発生せず、自動課金もありません。年間プランのクォータは毎月ずつ付与されます。

登録すれば無料で使えます

開発者登録をすると API キーを 1 個、月 1,000 回の呼び出し枠(IPv4 と IPv6 の合計)が使えます。購入を決める前に組み込みを完了させるには十分です。個人の開発・テスト用途に限ります。商用利用は下記プランをご利用ください。

無料で API キーを作成

API デベロッパー

¥19.9/月
  • 月 100,000 回
  • 5 QPS の同時実行
  • API キー 1 個
  • 許可リストは利用不可
  • エラーログ 7 日分
  • 商用利用可

API ビジネス

¥299.0/月
  • 月 5,000,000 回
  • 50 QPS の同時実行
  • API キー 5 個
  • IP/CIDR 許可リスト 100 件
  • エラーログ 90 日分
  • 商用利用可

エンタープライズ

¥999/月〜
  • クォータと同時実行数をカスタム
  • 契約と専用 SLA
  • 専任テクニカルサポート
  • オンプレミス導入に対応
お問い合わせ
クォータが足りない?慌ててアップグレードしなくて大丈夫

有料プランをご利用中の方は、いつでも単発の追加パックを購入できます:¥14.90 / 100,000 回、¥59.90 / 1,000,000 回。追加分は当期のクォータに上乗せされ、当期と同時に失効します。自動更新はありません。購入はコンソールから。

現在利用できる支払い方法:Stripe。SLA 付きの法人契約は、通常の商用プランとは別途ご提供します。

DATA

ついでにデータの話:IPv6 はどこまで普及したか

2026 年 2 月 5 日 以降に 17NAS の訪問者が実施した 181,053 回の実測(ユニーク IP 47,088 件)に基づきます。この判定は、まさにこのページで提供しているエッジネットワーク上で動いています。

デュアルスタック(IPv4 + IPv6)理想的な状態。両方のプロトコルが使える
61.2%108,517 回
IPv4 のみIPv6 が未開通、またはルーター / ファイアウォールで遮断されている
35.8%63,415 回
IPv6 のみ少数派。一部のモバイル回線や IPv6 シングルスタック環境
1.4%2,401 回
結果を取得できず回線が弱い、タイムアウト、プロキシ環境などで判定に失敗
1.6%2,763 回

合計で 62.6% の訪問者が IPv6 に対応しています。ただし注意点として、わざわざ 17NAS で IPv6 を測ろうとする人は、一般の利用者より IPv6 に関心が高い層です。つまりこのサンプルには自己選択バイアスがあり、全国的な普及率として読むことはできません。あくまで「IPv6 に関心のある人たち」の実態です。データは 1 時間ごとに更新。自分のネットワークを試すならIPv6 判定ツールはこちら。

REFERENCE

API リファレンス

まずは下の 3 ステップから。5 分で最初のリクエストが通ります。細かい仕様はその下に。

  1. 1
    API キーを作成する

    ログイン後、コンソールで「API キーを作成」をクリックします。キー全文が表示されるのは 1 回だけです。サーバーにはハッシュしか保存されないため、紛失した場合は再作成するしかありません。

    コンソールで作成する
  2. 2
    Bearer ヘッダーを付けてリクエストする

    キーを Authorization ヘッダーに入れ、/v1/ip を呼び出します。

    リクエスト例を見る
  3. 3
    レスポンスヘッダーでクォータを見る

    成功レスポンスには必ず X-Quota-Remaining が付くため、使用量を別途問い合わせる必要はありません。

    ヘッダーの説明を見る

認証

サーバーサイドのリクエストの Authorization ヘッダーで Bearer キーを送ります。

Authorization: Bearer 17nas_live_xxxxxxxxx

キーをブラウザのスクリプト、アプリ、ミニプログラムのパッケージに入れないでください。いずれも逆コンパイルされます。フロントで必要な場合は、自分のサーバーにリクエストさせ、サーバーが代理で呼び出します。コンソールで IP/CIDR 許可リストを設定すれば、送信元をさらに絞れます。

GET/v1/ip

ipapi.17nas.com

この HTTP 接続で実際に使われた IP とプロトコルを返します。IPv4 で来れば IPv4、IPv6 で来れば IPv6 が返り、指定は不要です。

パラメータ位置説明
AuthorizationHeader必須。Bearer <あなたの API キー>
formatQuery任意。json(既定)または text。text は IP のみを返すため、シェルでそのまま使えます
# JSON(既定)
curl https://ipapi.17nas.com/v1/ip \
  -H "Authorization: Bearer 17nas_live_xxx"

# IP のみのプレーンテキスト。シェル変数にそのまま入れられる
curl "https://ipapi.17nas.com/v1/ip?format=text" \
  -H "Authorization: Bearer 17nas_live_xxx"

# curl 自身のオプションで IPv4 / IPv6 を強制する
curl -4 https://ipapi.17nas.com/v1/ip -H "Authorization: Bearer 17nas_live_xxx"
curl -6 https://ipapi.17nas.com/v1/ip -H "Authorization: Bearer 17nas_live_xxx"

レスポンスフィールド

200 OK
{
  "ip": "203.0.113.10",
  "protocol": "IPv4",
  "country": { "code": "CN" },
  "region": "Guangdong",
  "city": "Shenzhen",
  "timezone": "Asia/Shanghai",
  "asn": { "number": 4134, "organization": "CHINANET" },
  "edge": { "colo": "HKG" },
  "request_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "generated_at": "2026-07-26T09:00:00.000Z"
}
フィールド型説明
ipstringこの接続のグローバル IP
protocolstringIPv4 または IPv6
country.codestringISO 3166-1 の 2 文字国コード。取得できない場合は null
region / citystring州・省と都市(英語)。精度はエッジ側のデータ次第で、null になることもあります
timezonestringIANA タイムゾーン名(例:Asia/Shanghai)
asn.numbernumber自律システム番号。取得できない場合は 0
asn.organizationstring通信事業者名。null の場合があります
edge.colostringこのリクエストを処理したエッジノードの 3 文字コード
request_idstringこのリクエストの一意な ID。問い合わせ時に添えてください

位置情報フィールドはエッジノードの GeoIP データに依存しており、モバイル回線、衛星回線、企業 NAT の出口、一部のプロキシでは不正確または空になることがあります。事実ではなく参考値として扱ってください。地域ブロックの強制判定には使わないでください。

クォータ関連ヘッダー

成功レスポンスには必ず現在のクォータ状況が付くため、別途問い合わせる必要はありません。

レスポンスヘッダー説明
X-RateLimit-Limit1 秒あたりの許可リクエスト数(QPS)
X-RateLimit-Remaining現在の 1 秒間に残っている回数
X-RateLimit-Resetレート制限ウィンドウがリセットされる Unix タイムスタンプ
X-Quota-Limit当期の総クォータ
X-Quota-Used当期の使用済み
X-Quota-Remaining当期の残り
X-Quota-Reset当期クォータのリセット時刻
X-Request-Idこのリクエストの ID。問い合わせ時に添えてください

コード側で X-Quota-Remaining を監視し、10% を切ったら通知しましょう。呼び出しが失敗してから気づくのでは遅すぎます。

エラーステータス

401 キーが無効、失効済み、または形式が不正 403 送信元 IP が許可リストにない 429 QPS 制限を超過、または当期のクォータを使い切った 503 一時的に利用できません。時間をおいて再試行
{
  "error": {
    "code": "quota_exhausted",
    "message": "Monthly quota exhausted",
    "request_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "docs_url": "https://17nas.com/ip-api.php#documentation",
    "upgrade_url": "https://17nas.com/ip-api.php?source=api-error&placement=quota-exhausted#pricing",
    "reset_at": "2026-08-01T00:00:00+08:00"
  }
}

429 には 2 つの原因があり、ヘッダーで区別できます。X-RateLimit-Remaining が 0 なら瞬間的なレート制限で、1 秒待てば再開できます。X-Quota-Remaining が 0 なら当期のクォータ切れで、reset_at を待つか、追加購入かアップグレードが必要です。

リトライとフォールバック

これはネットワークリクエストなので、必ず失敗するときがあります。実務的な指針をいくつか:

  • タイムアウトは 5 秒以内に。メイン処理を巻き込ませない
  • 503 やタイムアウトは指数バックオフ(1s・2s・4s)で最大 3 回までリトライ
  • 401 / 403 はリトライしない。設定の問題であり、再試行はクォータの無駄
  • クォータ切れによる 429 はリトライしても無意味。そのままフォールバック処理へ
  • 非クリティカルな処理(ログ記録など)は失敗したらスキップ。位置情報が取れないくらいでユーザーの正常な操作を止めない
  • 結果は数分ローカルにキャッシュしてよい。同じサーバーの出口 IP が秒単位で変わることはまずない
FAQ

購入前によくある質問

無料枠を商用利用できますか?

できません。無料の月 1,000 回は個人の開発・テスト専用です。自分のサイト、アプリ、ミニプログラム、顧客に納品するシステムなど、外部にサービスを提供する用途はすべて商用プランが必要です。有料プランではコンソールに「商用利用可」と表示されます。

クォータを使い切ったらどうなりますか?自動で課金されますか?

されません。クォータを使い切るとエンドポイントは 429 を返して停止します。未払いは発生せず、自動課金もありません。次の期間まで待って自動復帰させるか、追加パックを買ってすぐ続けるかを選べます。後払い課金をあえて採用していないのは、バグによる無限ループが高額請求につながらないようにするためです。

年払いのクォータは一括で付与されますか?

いいえ、毎月ずつ付与されます。年間の API Pro なら、月 100 万回を 12 か月連続で付与するのであって、1,200 万回を一括で渡すわけではありません。初月に異常な呼び出しで年間分を使い切ってしまうのを防ぐためです。各月の残りは翌月に繰り越されません。

支払い後、どのくらいで使えますか?

決済が完了すると、新しいクォータは 1 分以内に世界中のエッジノードへ反映されます。反映が終わるまでの呼び出しは従来のクォータで計算されるため、無駄になりません。コンソールで注文が「完了」になれば有効です。

返金はできますか?

API のクォータはデジタル商品のため、付与後の返金は原則としてお受けできません。ただし、当方の原因でサービスが利用できなかった場合や、支払い後にクォータが反映されなかった場合は、注文番号を添えてフィードバックページまでご連絡ください。個別に対応します。まずは無料枠で組み込みを完了させてからのご購入をおすすめします。

API キーが漏れてしまったら?

すぐにコンソールでそのキーを失効させ、新しいキーを作成してください。失効は 1 分以内にエッジへ反映されます。予防策として、あらかじめ IP/CIDR 許可リストを設定しておくことをおすすめします。そうすれば、キーが漏れてもサーバーの IP 以外からは使えません。

途中でプランをアップグレードできますか?

できます。コンソールで「プランをアップグレード」を選ぶと差額のみのお支払いで、有効期限は変わりません。アップグレードは現在の請求サイクルを維持します(月払いは月払いへ、年払いは年払いへ)。月払いから年払いに変えたい場合は、更新時に年払いを選んでください。

データはどこに保存されますか?何を照会したか記録されますか?

保存するのは集計された利用統計(1 時間ごとの成功/失敗回数、平均応答時間)とエラーログだけです。エラーログ内の送信元 IP はマスキングして保存し、保持日数はプランによります(7 日から)。照会の結果として返した IP の内容そのものは保存しません。

サービスの安定性はどう担保されていますか?

エンドポイントはグローバルエッジネットワーク上で動作し、リクエストは利用者に最も近いノードが応答します。単一のオリジンサーバーに戻さないため、ある地域のノードに障害が起きても全体が停止することはありません。契約上の SLA が必要な場合は、法人向けカスタムプランをご検討ください。

まだ決めきれませんか?

まずは無料枠で組み込みを完成させてください。動くのを確かめてから購入を判断すればよく、試すのは無料です。