そらまめくんAPIで大気汚染データを取る
そらまめくん(環境省 大気汚染物質広域監視システム)は、全国の大気汚染常時監視測定局が1時間ごとに測っているPM2.5・光化学オキシダント・窒素酸化物などの濃度を公開しているシステムで、APIも提供されています。利用登録もAPIキーも不要、個人情報の提供も一切不要で、URLを組み立てるだけでJSONが返ってきます。ただし、JSONなのに文字コードがShift_JISであるという、現代のHTTPクライアントを素直に詰ませる仕様があります。このガイドでは、取れるデータと実際に叩いて確認した罠を整理します。
取れるデータと単位
測定項目は16種類で、公式にそれぞれ単位が定義されています。大気汚染の主役であるPM2.5(微小粒子状物質)は μg/m3、SPM(浮遊粒子状物質)と SP(浮遊粉じん)は mg/m3 です。粒子状物質の中でPM2.5だけ単位が違うので、並べてグラフにするときは注意してください。
ガス系は、SO2(二酸化硫黄)・NO(一酸化窒素)・NO2(二酸化窒素)・NOX(窒素酸化物)・CO(一酸化炭素)・OX(光化学オキシダント)がいずれも ppm です。炭化水素系の NMHC(非メタン炭化水素)・CH4(メタン)・THC(全炭化水素)は ppmC という別の単位になります。
気象要素も同時に取れます。WD(風向)・WS(風速, m/s)・TEMP(気温, ℃)・HUM(湿度, %)です。汚染物質の濃度は風向・風速に強く影響されるため、同じAPIで一緒に取れるのは実務上ありがたい設計です。
データは1時間ごとに更新され、24時間提供されています。システムは2001年から運用されています。
APIの叩き方
エンドポイントは `https://soramame.env.go.jp/soramame/api/data_search` です。パラメータは次のとおりです。
必須が2つあります。`Start_YM`(取得開始年月、YYYYMM形式。例: 202606)と、`TDFKN_CD`(都道府県コード、01〜47)です。都道府県コードを付け忘れると、`{"code":"PG-05-001","message":"パラメータが不正です...TDFKN_CD","status":400}` という、コード付きの丁寧なJSONエラーが返ります。エラー設計は良質です。
任意パラメータは3つ。`End_YM`(省略すると現在の年月まで)、`SKT_CD`(測定局コード。カンマ区切りで複数指定可)、`REQUEST_DATA`(取得したい項目。カンマ区切り。例: NOX,TEMP)です。項目を絞らないと全16項目が返るので、必要なものだけ指定するとレスポンスが軽くなります。
実際に東京都のある測定局のPM2.5を1か月分取得したところ、HTTP 200 で約24KB、応答は0.1秒でした。中身は `[{"SKT_CD":"13101010","SKT_DATE":"2026/07/01","SKT_TIME":"01","PM2_5":"8"}, ...]` という素直な配列で、1時間ごとに1レコードです。
最大の罠:JSONなのにShift_JISで返る
レスポンスヘッダを見ると `Content-Type: application/json;charset=SJIS` です。JSONの仕様(RFC 8259)はUTF-8を必須としているのですが、このAPIはShift_JISで返してきます。
何が起きるかというと、JavaScriptの `fetch()` は本文をUTF-8として解釈するため、日本語が文字化けします。実際にエラーメッセージを取得すると、`パラメータが不正です` のはずが読めない文字列になりました。数値データだけを扱っているうちは気づきませんが、エラーメッセージを表示しようとした瞬間に化けます。
対処としては、レスポンスをテキストとして受け取らず、バイト列(ArrayBuffer)で受け取ってから Shift_JIS としてデコードする必要があります。JavaScriptなら `TextDecoder('shift_jis')`、Pythonなら `response.content.decode('cp932')` です。「JSONだからUTF-8だろう」という前提でライブラリ任せにすると詰まります。
パラメータ名と値の癖
PM2.5を指定するパラメータ名は `PM2_5` です。ドットではなくアンダースコアで、レスポンスのフィールド名も同じく `PM2_5` になります。「PM2.5」「PM25」と書いても通りません。地味ですが最初に必ず引っかかります。
欠測や非測定の項目は、null でも空文字でもなく、半角スペースで埋められて返ってきます。測定局によって測っている項目が違うため、たとえばSO2やOXを測っていない局では、その列が毎時ずっと空白になります。「値が0」と「測っていない」は区別が必要なので、空白を0として集計しないよう気をつけてください。
そして解釈上の最重要事項として、**このAPIが返すのは速報値です**。公式に「即時性を重視して、データ検証を待たずに速報値として一般に提供している」と明記されています。研究や公的な分析に使う場合、後から確定値で訂正される可能性を前提にする必要があります。速報値であることは、グラフや記事に明記すべき情報です。
サイトはSPAなので、内部のパスを推測して叩かない
実装上の注意として、そらまめくんのサイトはJavaScript必須のSPA(シングルページアプリケーション)で構築されており、サーバーがcatch-allルーティングになっています。存在しないパスを叩いても404ではなく、**HTTP 200 とともにトップページのHTMLが返ってきます**。
これは、ブラウザの開発者ツールで見つけた内部のCSVパスなどを直接叩くコードを書いたときに危険です。そのパスが将来移設・廃止されても、エラーにならず200が返り続けるため、`response.ok` のチェックだけでは異常を検知できません。HTMLをCSVやJSONとしてパースした結果、意味不明なデータを「成功」として受け取ってしまいます。
上で紹介した `soramame/api/data_search` が正式なAPIなので、必ずこちらを使ってください。内部パスに依存する場合は、最低でも `Content-Type` を検証し、期待した形式でなければエラーとして扱う実装にしておくべきです。
利用条件
公式のAPI説明ページに、「利用される方のいかなる情報も提供していただくことなく、ご利用いただけます。また、個人情報の収集などは行いません」と明記されています。登録も申請も不要です。
アクセスログについては、利用動向の調査などサイト運営のために使用されることがあるものの、個人の特定は行わないと説明されています。ただし不正アクセスやDoS攻撃があった場合、公的機関からの法令に基づく情報提供要請には応じる旨も書かれています。常識的な頻度で利用してください。
出典
元システムエンジニア。Web系アプリ開発6年+ソリューション9年、IT実務およそ15年。個人開発者として、政府オープンデータや各府省のAPIを実際に叩いて検証し、「何が取れるか」「実装時にどこで詰まるか」「どう活用するか」を一次検証にもとづいて記録しています。
運営者・検証方針について →