GASでWeb APIを呼ぶ|UrlFetchAppとJSONの基本

「GASから外部のAPIを呼べるらしい」と聞いて調べてみたものの、UrlFetchApp とか JSON.parse とか、いきなり知らない単語が並んで手が止まってしまった……。私も最初はそうでした。

しかも、コードをコピペして動かしたのに、エラーも出ないのにシートが空のまま。「何が起きているの?」となるのが、API初心者のあるあるですよね。

この記事では、APIキーがいらない公開APIを使って、GASでデータを取得し、スプレッドシートに書き込むまでを、小さなコードで一緒にやってみましょう。最後に、失敗したときに原因が分かるよう、エラーの確認方法もつけます。

💡
この記事でわかること
  • UrlFetchApp でGET通信する基本形
  • JSONを JSON.parse で扱う方法
  • 取得したデータをシートに書き込む方法
  • レスポンスコードの確認と try/catch でのエラー処理
  • よくあるつまずきと確認ポイント

結論:UrlFetchAppで取得し、JSON.parseで読めばいい

先に結論です。

  • 外部のURLにアクセスするには、GASの UrlFetchApp.fetch(url) を使います
  • 返ってきた文字列は、getContentText() で取り出し、JSON.parse() でJavaScriptの配列やオブジェクトに変換します
  • 変換できたら、あとは普通の配列として、シートに書き込めます
  • 失敗に気づけるよう、レスポンスコードの確認と try/catch を入れておきます

UrlFetchAppでAPIを呼び、JSON.parseで読み取ってシートに書き込むまでの流れ(途中でレスポンスコードを確認する)を示した図

準備:使う公開APIとシートを用意する

今回は、練習用に公開されている JSONPlaceholder の投稿データAPIを使います。APIキーの登録は不要なので、すぐに試せます。

  • 1
https://jsonplaceholder.typicode.com/posts?_limit=5

このURLをブラウザで開くと、投稿データが5件、JSONで表示されます。形は次のような配列です(値は省略しています)。

  • 1
  • 2
  • 3
  • 4
[
  { "userId": 1, "id": 1, "title": "(タイトルの文字列)", "body": "(本文の文字列)" },
  { "userId": 1, "id": 2, "title": "(タイトルの文字列)", "body": "(本文の文字列)" }
]

📝
実際のAPIを使うときの注意

別のAPIを使うときは、そのサービスの利用規約や、キーの要否を事前に確認してください。この記事の例は、練習用のAPIだけを使っています。

シートの準備はこの2つです。

  1. Googleスプレッドシートを新しく作り、シート名を posts にします
  2. 「拡張機能」→「Apps Script」を開きます

エディタの開き方に不安があれば、Googleスプレッドシートを開くための手順も見ておきましょう。


まずはGETして、中身をログで見てみる

いきなりシートに書くのではなく、最初は「ちゃんと取れているか」をログで見るところから始めましょう。

  • 1
  • 2
  • 3
  • 4
  • 5
function fetchTest() {
  const response = UrlFetchApp.fetch('https://jsonplaceholder.typicode.com/posts?_limit=5');
  console.log(response.getResponseCode());
  console.log(response.getContentText());
}

  1. 上のコードを貼って保存し、fetchTest を選んで「実行」します
  2. 初回は承認を求める画面が出るので、案内に従って許可します
  3. 画面下の実行ログに、200 と、JSONの文字列が出ていれば成功です

200 はHTTPのステータスコードで、「正常に取得できた」という意味です。getContentText() で返ってくるのは、まだただの文字列です。ここがポイントなので、次で変換します。


JSON.parseで配列にして、シートに書き込む

文字列のままではシートに書けないので、JSON.parse() でJavaScriptの配列に変換します。変換後は、post.id や post.title のように、キーの名前で値を取り出せます。

次が、シートへの書き込みまで含めたコードです。

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
const API_URL = 'https://jsonplaceholder.typicode.com/posts?_limit=5';
const SHEET_NAME = 'posts';

function importPosts() {
  const response = UrlFetchApp.fetch(API_URL);
  const posts = JSON.parse(response.getContentText());

  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(SHEET_NAME);
  const rows = posts.map(post => [post.id, post.userId, post.title]);

  sheet.clearContents();
  sheet.getRange(1, 1, 1, 3).setValues([['id', 'userId', 'title']]);
  sheet.getRange(2, 1, rows.length, 3).setValues(rows);
}

流れを分けて見てみましょう。

処理 使っているもの
APIにアクセスする UrlFetchApp.fetch(API_URL)
文字列を配列に変換する JSON.parse(response.getContentText())
必要な項目だけを取り出す posts.map(post => [post.id, post.userId, post.title])
シートを一度空にする sheet.clearContents()
見出しとデータを書く getRange(...).setValues(...)

setValues() には、「行の配列の配列」を渡す必要があります。map で [[1, 1, 'タイトル'], ...] の形にしているのは、そのためです。

実行して、シートに見出しと5行のデータが入れば成功です。コードの実行方法に迷ったら、GoogleAppsScriptのコードを実行する方法を見てみてください。


エラーに気づけるようにする(レスポンスコードと try/catch)

ここまでのコードは、うまくいく前提で書いています。ただ、現実にはURLを打ち間違えたり、相手のサービスが止まっていたりします。そこで、失敗に気づける形に書き直します。

UrlFetchApp.fetch() は、既定ではHTTPエラー(4xxや5xx)のときに例外を投げて止まります。一方、オプションの muteHttpExceptions: true を付けると、エラーでも例外にならず、レスポンスコードを自分で確認できます。今回はこちらを使って、コードを自分で見て判断します。

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
const API_URL = 'https://jsonplaceholder.typicode.com/posts?_limit=5';
const SHEET_NAME = 'posts';

function importPosts() {
  try {
    const response = UrlFetchApp.fetch(API_URL, { muteHttpExceptions: true });
    const code = response.getResponseCode();
    if (code !== 200) {
      throw new Error(`APIがエラーを返しました(HTTP ${code})`);
    }

    const posts = JSON.parse(response.getContentText());
    if (posts.length === 0) {
      throw new Error('取得できたデータが0件でした');
    }

    const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(SHEET_NAME);
    if (!sheet) {
      throw new Error(`シート「${SHEET_NAME}」が見つかりません`);
    }

    const rows = posts.map(post => [post.id, post.userId, post.title]);
    sheet.clearContents();
    sheet.getRange(1, 1, 1, 3).setValues([['id', 'userId', 'title']]);
    sheet.getRange(2, 1, rows.length, 3).setValues(rows);
    console.log(`${rows.length}件を書き込みました`);
  } catch (e) {
    console.error(e.message);
    throw e;
  }
}

確認しているポイントは3つです。

  1. レスポンスコードが200かどうか
  2. データが0件ではないか
  3. シートが存在するか

catch の中では、メッセージをログに出したうえで、throw e で改めてエラーにしています。こうしておくと、実行ログに「失敗」として残ります。握りつぶしてしまうと、失敗しているのに成功に見えてしまうので気をつけましょう。

試しに、API_URL の posts を postss のように間違えて実行してみてください。404が返ってきて、ログに「APIがエラーを返しました」と出るはずです。


よくあるつまずき

症状 よくある原因 確認すること
Cannot read properties of null が出る シート名が違う、または単体のスクリプトで getActiveSpreadsheet() を使っている シート名が posts か。スプレッドシートの「拡張機能」→「Apps Script」から開いたか
シートが空のまま 実行に失敗している、または別のシートを見ている 実行ログのエラーを確認する
HTTP 404 が返る URLの打ち間違い ブラウザで同じURLを開いて確認する
SyntaxError が出る 返ってきたものがJSONではない(HTMLなど) console.log(response.getContentText()) で中身を見る
承認の画面が出る 初回に外部へ接続する許可が必要 内容を確認して、許可する
前回のデータが残っている シートを空にしていない clearContents() を入れているか確認する

APIまわりで困ったら、まず「ステータスコード」と「返ってきた文字列」をログに出すことをおすすめします。原因の半分は、これで分かります。


次の一歩

公開APIで1回できたら、次は応用です。

GAS全体の学ぶ順番を整理したい方は、GAS学習の進め方|既存記事をつなぐ学習マップが参考になります。

また、GASではなく「何かが起きたらAPIで通知を受け取って動かす」方向に進みたい方は、n8nのトリガー設計|Webhookで始める「起きたら動く」自動化も読んでみてください。


関連する本・記事

本:『Google Apps Script × 生成AI 全自動仕事術』

GASで日々の作業を自動化する流れを、生成AIに頼みながら進める本です。コードを一から書くのが不安な方に向いています。

記事: