JavaScriptから法人番号APIを使う方法とCORSの注意点

JavaScriptから国税庁の法人番号システムWeb-APIを使うときは、ブラウザから直接呼ばず、サーバー側(Node.jsやNext.jsのAPIルート)から呼んで、結果だけをブラウザに返すのが正解です。
ブラウザから直接呼ぶと、CORSのエラーで失敗しやすいうえに、利用規約で禁止されているアプリケーションIDの開示になってしまいます。この記事では、その理由と実装例を説明します。法人番号を扱えるAPIの比較は法人番号APIの比較にまとめています。
ブラウザから直接呼んではいけない2つの理由
1. アプリケーションIDが利用者に見えてしまう
法人番号APIは、URLの id パラメータにアプリケーションIDを付けて呼びます。ブラウザで動くJavaScriptから呼ぶと、開発者ツールを開けば誰でもIDを見られます。
Web-API機能利用規約は、アプリケーションIDを第三者に開示することを禁止しています。IDが漏れると、他人に使われて利用を止められるおそれもあります。
2. CORSのエラーになる
ブラウザは、別のドメインのAPIを呼ぶときに、相手側がCORSのヘッダーで許可しているかを確かめます。国税庁のAPIはブラウザから呼ばれる前提で作られていないため、自分のサイトから fetch すると、次のようなエラーで止まります。
Access to fetch at 'https://api.houjin-bangou.nta.go.jp/...' from origin 'https://example.com'
has been blocked by CORS policyCORSのエラーを回避するプロキシを挟んでブラウザから呼ぶ方法もありますが、結局アプリケーションIDの問題が残ります。サーバー側で呼ぶのが一番安全です。
Node.jsで呼ぶ
Node.js 18以降は fetch が標準で使えます。XMLの解析には fast-xml-parser を使います。
npm install fast-xml-parserimport { XMLParser } from "fast-xml-parser";
const parser = new XMLParser();
export async function fetchCorporations(numbers) {
const url = new URL("https://api.houjin-bangou.nta.go.jp/4/num");
url.searchParams.set("id", process.env.NTA_APP_ID);
url.searchParams.set("number", numbers.join(","));
url.searchParams.set("type", "12");
const res = await fetch(url);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const xml = await res.text();
const corps = parser.parse(xml).corporations?.corporation ?? [];
// 1件だけのときは配列にならないのでそろえる
return (Array.isArray(corps) ? corps : [corps]).map((c) => ({
corporateNumber: String(c.corporateNumber),
name: c.name,
address: `${c.prefectureName}${c.cityName}${c.streetNumber}`,
}));
}fast-xml-parser は、法人番号のような数字だけの値を数値に変換します。13桁でも桁が落ちることはありませんが、先頭が0の値や郵便番号を扱うなら、new XMLParser({ parseTagValue: false }) にして文字列のまま受け取るほうが安全です。
Next.jsのAPIルートで包む
ブラウザからは自分のサーバーのAPIを呼び、サーバーが国税庁のAPIを呼ぶ形にします。Next.jsのApp Routerなら次のようになります。
// app/api/corporations/[number]/route.js
import { fetchCorporations } from "@/lib/nta";
export async function GET(_request, { params }) {
const { number } = await params;
if (!/^\d{13}$/.test(number)) {
return Response.json({ error: "法人番号は13桁の数字です" }, { status: 400 });
}
const [corp] = await fetchCorporations([number]);
return corp
? Response.json(corp)
: Response.json({ error: "見つかりません" }, { status: 404 });
}ブラウザ側は、自分のドメインの /api/corporations/1180301018771 を呼ぶだけです。CORSの問題も、IDの開示の問題も起きません。
入力された法人番号は、13桁の数字かどうかに加えて、チェックデジットでも確かめておくと、無駄なアクセスを減らせます(法人番号のチェックデジットの計算方法)。
気をつけること
- 呼びすぎを防ぐ: フォームの入力のたびに呼ぶと、短時間の大量アクセスになります。13桁がそろってから呼ぶ、結果をキャッシュする、などの工夫をしてください。
- 10件ずつ: 1回に指定できる法人番号は10件までです。
- 出典の表示: 取得した情報を表示するサービスを公開するなら、国税庁のWeb-APIを使っている旨と、国税庁が内容を保証しない旨を表示します。
JSONで扱いたい場合
国税庁のAPIの応答はCSVかXMLで、JSONは選べません。JavaScriptで扱いやすいJSONで受け取りたい場合の方法は、法人番号APIをJSONで使う方法で解説しています。
まとめ
JavaScriptから法人番号APIを使うときは、サーバー側で呼んで結果だけをブラウザに返します。CORSのエラーを避けるためだけでなく、アプリケーションIDを守るためでもあります。
ブラウザから直接呼べる形の商用APIもあります(APIキーはサーバー側で保管する前提です)。選択肢は法人番号APIの比較を見てください。





