Claude Media
不動産情報ライブラリAPIをClaude Codeで呼ぶ — 取引価格・地価を取得して根拠表にする

不動産情報ライブラリAPIをClaude Codeで呼ぶ — 取引価格・地価を取得して根拠表にする

国土交通省の不動産情報ライブラリAPIで、市区町村と期間を指定して取引価格を取得し、事例の比較表にするまでをClaude Codeに任せる手順。APIキーの申請、404の扱い、地価公示の引き方、出典表示も扱います。

不動産の取引価格や地価公示は、国土交通省の「不動産情報ライブラリ」でAPIとして公開されています。Claude Codeに取得スクリプトを書かせれば、市区町村と期間を指定して事例を集め、比較表にするところまでを一気に回せます。

ただしこのAPIは、キーの申請から出力の読み方まで、つまずく場所がいくつもあります。マニュアルのサンプルコードにも、そのまま動かすと止まる箇所があります。この記事では、使うAPIの選び方、キーの置き方、取引価格の取得スクリプト、データに現れる癖、出典表示の決まりを順に扱います。

不動産情報ライブラリAPIで引けるデータと使うAPI

不動産情報ライブラリは、不動産の取引価格・地価公示などの価格情報、防災情報、都市計画情報、周辺施設情報を見られる国土交通省のWEBサイトです。APIの出力形式はPBFとGeoJSONの2種類で、位置情報を持つAPIではXYZでタイルを指定して取得します。

価格を扱う記事で使うのは、公開API一覧のうち次の5本です。

IDAPI名整備範囲絞り込みの単位
XIT001API名不動産価格(取引価格・成約価格)情報取得整備範囲取引価格は2005年第3四半期以降、成約価格は2021年第1四半期以降絞り込みの単位都道府県・市区町村・駅
XIT002API名都道府県内の市区町村一覧整備範囲地方公共団体コードに準拠絞り込みの単位都道府県
XCT001API名鑑定評価書情報整備範囲直近5年分絞り込みの単位都道府県・用途区分
XPT001API名取引価格・成約価格のポイント(点)整備範囲XIT001と同じ絞り込みの単位XYZタイル
XPT002API名地価公示・地価調査のポイント(点)整備範囲地価公示は1995年以降、地価調査は1997年以降絞り込みの単位XYZタイル

市区町村と期間で事例を引く用途なら、中心はXIT001です。市区町村コードを調べるためにXIT002を前に挟みます。XPT系はタイル座標を計算して渡す必要があり、地図表示向けの作りです。

APIキーの申請と置き方

APIの利用には、利用約款への同意と申請画面での入力が必要です。申請が審査・承認されるとAPIキーが発行されます。審査結果は申請後5営業日を目安にメールで届き、迷惑メールフォルダに入る場合もあります。

利用者種別は、法人・法人以外の団体・個人の3つから選びます。申請ページによると、この種別は反社会的勢力に該当しないかの審査と、利用者の属性の把握に使われます。個人で取ったキーを法人利用に切り替える場合は、問い合わせ画面から手続きします。

手順

キーを取ってからClaude Codeに渡すまで

  1. 1

    API利用申請をする

    利用約款に同意し、利用者種別などを入力して申請します。受付完了メールは送付が停止されています。

  2. 2

    承認メールを待つ

    目安は5営業日です。届かないときは迷惑メールフォルダを確かめます。

  3. 3

    キーを環境変数に置く

    コードやCLAUDE.mdにキーを書かず、環境変数から読ませます。

呼び出し方も決まっています。キーはリクエストヘッダー Ocp-Apim-Subscription-Key に設定し、HTTPSで送ります。マニュアルは、CORSエラーを避けるためにブラウザからAPIリクエストを送らないよう求めています。スクリプトはサーバー側かローカルで動かす前提です。

export REINFOLIB_API_KEY="(承認メールで届いたキー)"

.env にキーを書いて使うなら、Claude Codeの権限設定で読み取りを拒否できます。Claude Codeのpermissionsには Read(./.env) が例として載っています。

{
  "permissions": {
    "deny": ["Read(./.env)"]
  }
}

このルールが確実に効くのはClaudeのファイルツールです。GrepやGlobなどの組み込みツールには、docsの表現で「ベストエフォート」で適用されます。Bashで cat .env を許可したままだと読めてしまう可能性があるので、Bashの許可範囲もあわせて見ます。

市区町村と期間を指定して取引価格を取る

XIT001のパラメータで必須なのは year だけです。ただし area(都道府県コード)・city(市区町村コード)・station(駅コード)のうち少なくとも1つは指定する必要があります。

  • year: 取引時期(西暦4桁)。取引価格は2005年(第3・第4四半期のみ)から、成約価格は2021年から指定できる
  • quarter: 1〜4(1が1〜3月、2が4〜6月、3が7〜9月、4が10〜12月)
  • city: 地方公共団体コードの上5桁
  • priceClassification: 01 が取引価格のみ、02 が成約価格のみ、未指定で両方
  • language: ja(既定)または en

市区町村コードは、XIT002に都道府県コードを渡すと一覧で返ります。東京都なら area=13 で、千代田区が 13101 のように返る例がXIT002のページに載っています。まずコマンド1本で通るかを確かめます。

curl -H "Ocp-Apim-Subscription-Key:$REINFOLIB_API_KEY" --compressed \
  "https://www.reinfolib.mlit.go.jp/ex-api/external/XIT002?area=13" \
  > XIT002.json
curl -H "Ocp-Apim-Subscription-Key:$REINFOLIB_API_KEY" --compressed \
  "https://www.reinfolib.mlit.go.jp/ex-api/external/XIT001?year=2015&quarter=2&city=13102&priceClassification=01" \
  > XIT001.json

--compressed が付いているのは、出力がgzipでエンコードされているためです。XIT001・XIT002のページのコマンド例も同じ形で、都道府県内の一覧と取引価格の例を載せています。

公式サンプルのPythonコードで止まる箇所

マニュアルのPythonサンプルは、gzipの場合に gzip.decompress(data) を呼びます。しかしコード冒頭のimportは urllib.request と json の2つで、gzip が含まれていません。レスポンスのContent-Encodingがgzipだと NameError になる書き方です。

Claude Codeにサンプルを写させるときは、import gzip を足すよう指示に入れておきます。次の節のスクリプトでは、はじめから gzip を読み込んでいます。

事例の比較表を作るスクリプト

Claude Codeに「渋谷区の直近2年の事例を一覧にして」とだけ頼むと、市区町村コードを記憶から出すことがあります。コードはXIT002の応答から取らせる形にして、取得 → 絞り込み → 表の出力を1本にまとめます。次はマニュアルの項目名から組んだ例です。

import gzip
import json
import os
import statistics
import time
import urllib.error
import urllib.parse
import urllib.request
 
BASE = "https://www.reinfolib.mlit.go.jp/ex-api/external/"
KEY = os.environ["REINFOLIB_API_KEY"]
 
 
def call(api, **params):
    url = BASE + api + "?" + urllib.parse.urlencode(params)
    req = urllib.request.Request(url)
    req.add_header("Ocp-Apim-Subscription-Key", KEY)
    try:
        with urllib.request.urlopen(req) as res:
            raw = res.read()
    except urllib.error.HTTPError as e:
        if e.code == 404:  # XIT001 / XIT002 はデータが無いと404
            return None
        raise
    if raw[:2] == b"\x1f\x8b":  # gzipの先頭バイト
        raw = gzip.decompress(raw)
    return json.loads(raw)
 
 
def records(body):
    # 出力例がマニュアルに載っていないため、最初は構造を確認する
    if isinstance(body, list):
        return body
    return body.get("data", [])
 
 
def num(value):
    try:
        return float(value)
    except (TypeError, ValueError):
        return None
 
 
rows = []
for year, quarter in [(2024, 1), (2024, 2), (2024, 3), (2024, 4)]:
    body = call("XIT001", year=year, quarter=quarter,
                city="13113", priceClassification="01")
    time.sleep(1)  # 連続リクエストを避ける
    if body is None:
        print(f"{year}Q{quarter}: 該当データなし")
        continue
    rows += records(body)
 
lands = []
for r in rows:
    price, area = num(r.get("TradePrice")), num(r.get("Area"))
    if price is None or not area:
        continue  # 面積が数値でない行は除外し、件数を表示する
    lands.append((r["Period"], r["DistrictName"], r["Type"],
                  area, price, price / area))
 
print(f"取得 {len(rows)} 件 / 単価を計算できた {len(lands)} 件")
print("| 取引時点 | 地区 | 種類 | 面積(㎡) | 総額(円) | ㎡単価(円) |")
print("|---|---|---|---|---|---|")
for p, d, t, a, tp, u in sorted(lands):
    print(f"| {p} | {d} | {t} | {a:g} | {tp:,.0f} | {u:,.0f} |")
if lands:
    print(f"\n中央値(㎡単価): {statistics.median(x[5] for x in lands):,.0f} 円")
print("\n出典: 国土交通省 不動産情報ライブラリ"
      "(https://www.reinfolib.mlit.go.jp/)をもとに加工して作成")

13113 は渋谷区のコードです。実際のコードはXIT002で確認してから差し替えます。

初回の実行で見ること

XIT001の出力例は公式ページで空欄になっていて、応答の最上位の形が載っていません。records() が data キーを前提にしているのはそのためで、初回は応答の形を確かめてから表に進みます。

初回は、応答のキー一覧と先頭1件だけを表示させます。想定と違えば、records() を直します。

まず1回だけXIT001を呼び、応答の最上位のキーと先頭1件をそのまま表示して。
表の作成には進まないで。

数値の項目はどれも文字列型で返ります。TradePrice(取引価格の総額)や Area(面積)も文字列で返るため、計算の前に数値へ変換します。上のコードで float() を通しているのはそのためです。

比較表に載せる前に確かめるデータの癖

APIの仕様とサイトの利用規約から、比較表を作る前に確認したい点を挙げます。

確認点

根拠表にする前の確認

  • 404はエラーでなく該当なし

    タイルを指定しないXIT001・XIT002・XCT001は、データが無いと404を返します。タイルを指定するAPIは、空の配列と200です。

  • 種類が混ざっている

    Type には「宅地(土地と建物)」などが入り、Region に商業地などの地域区分が入ります。土地だけの事例と建物付きの事例を同じ表で比べると単価の意味が変わるため、Type で絞ります。

  • 取引価格は加工済みの情報

    利用規約は、取引価格情報を、アンケート調査の回答から個別の物件を特定できないよう加工したものと定義しています。

  • 地区コードは継続性を保証しない

    DistrictCode は、データ更新のタイミングで変わることがあります。過去に取得したコードや地区名との継続性は保証されていません。

次の2点は、表の読み方に直接響きます。

  • PriceCategory で、取引価格と成約価格のどちらの行かを区別できる。両方を混ぜて中央値を出すと、性質の違う価格が混ざる。priceClassification=01 で取引価格だけに揃えるのが簡単
  • Remarks(取引の事情等)の欄は、比較表の備考列に残しておく。記載のある行を集計に含めるかは、表の目的に合わせて決める

駅で絞る場合は注意があります。駅コードは国土数値情報の駅データのグループコード(N02_005g)を指定するもので、一部の駅コードは対応する駅データがなく、400エラーになる場合があります。その場合は、駅が属する都道府県か市区町村で指定し直します。

地価公示・地価調査を根拠表に足す

取引事例の横に公示価格を並べたいときは、地価公示・地価調査のAPIを使います。使える場面が違う2本があります。

XCT001(鑑定評価書情報)は、year・area・division の3つがすべて必須です。year は2022〜2026の範囲で、最新年から5年分だけが指定できます。division は 00 が住宅地、05 が商業地といった用途区分です。出力には、価格時点、標準地番号の地域名、1㎡当たりの価格、路線価の項目があります。

XPT002(地価公示・地価調査のポイント)は、response_format・z・x・y・year が必須です。ズームレベルは13〜15で、XYZタイルの座標を指定します。出力には対象年、標準地の番号、当年価格、前年価格、対前年変動率、地積、最寄り駅までの道路距離などが入ります。

XCT001は都道府県と用途区分で指定するため、タイル座標は要りません。XPT002のようにタイル座標を使う場合は、住所を緯度経度にしてからタイルに変換する手順が必要になります。住所の座標化は国土地理院の住所検索APIの記事にまとめています。

地価公示の価格は、利用規約の説明では、売り急ぎや買い進みなどの特殊な事情がない取引で成立すると認められる「正常な価格」です。近隣地域の標準的な画地の価格で、最高でも最低でもありません。個別の土地の価格を出すには、地積・形状・接面道路などの要因を標準地と比べる必要があります。取引事例の価格と並べる表では、列の意味を分けて書きます。

出典表示と使い方の線引き

比較表を資料にするときは、規約の次の決まりを守ります。

  • コンテンツを利用するときは出典を記載する。例は「出典:国土交通省 不動産情報ライブラリ(https://www.reinfolib.mlit.go.jp/ または該当ページのURL)」
  • 編集・加工して使うときは、利用したコンテンツの名称と、編集・加工したことも書く。「(国土交通省)をもとに○○株式会社作成」の形が例示されている
  • 編集・加工した情報を、国が作成したかのように公表・利用してはいけない
  • コンテンツは参考情報としての利用が想定されており、不動産取引の重要事項説明や建築確認申請などの手続に用いることは保証されていない
  • 「不動産情報ライブラリ」という名称を使った製品・サービス・アプリ名は、国土交通省が認めた場合を除いて認められていない

最後の2つは、成果物の位置づけに響きます。この表は参考情報であり、手続の書類にそのまま使えることを保証するデータではありません。上のスクリプトの末尾に出典の一文を出力させているのは、このためです。

リクエスト数にも触れておきます。リクエスト数に明確な上限はありませんが、同一キーで基準期間内に多数のリクエストがあるとアクセス制限がかかります。連続実行は避けて間隔を空ける必要があるので、スクリプトの四半期ごとのループには time.sleep(1) を入れています。

CLAUDE.mdに書いておく取得ルール

毎回の指示で同じ注意を繰り返さずに済むよう、プロジェクトのCLAUDE.mdに規約を置きます。次は書き方の一例です。

## 不動産情報ライブラリAPI
- キーは環境変数 REINFOLIB_API_KEY から読む。値を出力・コミットしない
- 市区町村コードは XIT002 の応答から取る。記憶で書かない
- リクエストは1秒以上あけ、ブラウザからは送らない
- 404 は「該当データなし」として扱い、エラー終了しない
- 数値項目は文字列で返る。変換できない行は件数を出して除外する
- 出力する表には必ず出典を付ける
  「出典: 国土交通省 不動産情報ライブラリ」と、加工した旨
- 取引価格と成約価格、土地と土地建物は混ぜて集計しない

e-Stat APIの記事でも、IDやコードを記憶で書かせず、応答から取らせる形を勧めています。コードを名前から推測させない点は、政府系APIに共通する注意です。取引先の名前を突き合わせる場面は法人番号Web-APIの記事が参考になります。

表ができたあと、収支の計算に進む

取引事例の㎡単価が出たら、同じ地域の物件の収支を試算する段階に進めます。収益物件の収支シミュレーションは、Claude for Excelでの不動産投資の収支シミュレーションで手順を書いています。ここで作った比較表の中央値を、購入価格の目安を考える材料として渡せます。

よくある質問

英語で出力できるか

language に en を指定すると、Type や Municipality など、出力表で「languageの設定に合わせた言語で出力」と注記された項目が英語になります。省略時は日本語です。

まとめ

不動産情報ライブラリAPIで事例の比較表を作る流れは、XIT002で市区町村コードを確定し、XIT001で期間ごとに取引価格を取り、数値に変換して表にする3段です。Claude Codeに任せるときは、コードを記憶で書かせないこと、404と文字列の数値を想定すること、出典を出力に入れることの3点をCLAUDE.mdに置いておけば、毎回の指示が短く済みます。

公式サンプルのPythonコードに import gzip が無いことと、XIT001の出力例が空欄であることは、初回に確認する価値があります。最初は1四半期・1市区町村で応答の形を見て、そこから期間を広げる進め方が安全です。

この記事を共有:XはてブLinkedIn