- クラウドサービス
GASで外部APIを呼び出す UrlFetchAppとAPIキーの保存方法
GAS(Google Apps Script)で外部APIを呼び出すには、UrlFetchApp.fetch に URL とオプションを渡し、返ってきた HTTPResponse から応答コードと本文を取り出します。 APIキーはコードに直接書かず、スクリプト プロパティに保存して実行時に読み込みます。
この記事では、APIキーの読み込み・応答コードでの分岐・待機つきの再試行・入れ子の JSON を表にする処理・シートへの一括書き込みを1つにまとめたコードと、fetch のオプション、HTTPResponse のメソッド、3種類のプロパティ、割り当て上限の一覧表を載せます。
確認環境:Google Apps Script の公式リファレンスとガイド(UrlFetchApp、HTTPResponse、Properties サービス、割り当て)を 2026-10-05 に開いて照合しました。掲載コードは Node.js 22.22.2 で構文を検査し、TypeScript 7.0.2 と型定義 @types/google-apps-script 2.0.13 で、メソッド名と引数の型が合うことを検査しています。再試行と表への変換の動きは、UrlFetchApp などを代役のオブジェクトに差し替えて Node.js で動かした結果です。Google のサーバー上での出力例は載せていません。
この記事の結論
- APIキーはスクリプト プロパティに保存します。
PropertiesService.getScriptProperties().getProperty('API_KEY')で読み込み、コードには書きません。 - fetch には
muteHttpExceptions: trueを付けます。 4xx や 5xx でも例外にならず HTTPResponse が返るので、getResponseCode()で分岐できます。 - 再試行するのは 429 と 5xx だけにします。 401 や 404 は待っても結果が変わらないので、すぐに内容を表示して止めます。
- シートへの書き込みは、2次元配列にして
setValuesを1回だけ呼びます。 行ごとに書き込むより呼び出しの回数が少なくなります。 - 複数の URL をまとめて取るなら fetchAll、1件ずつ結果を見て次を決めるなら fetch を使います。
UrlFetchAppの早見表
| やりたいこと | 書き方 |
|---|---|
| GET で取得する | UrlFetchApp.fetch(url) |
| オプションを付けて取得する | UrlFetchApp.fetch(url, { method: 'get', headers: {...} }) |
| JSON を POST する | { method: 'post', contentType: 'application/json', payload: JSON.stringify(obj) } |
| フォーム形式で POST する | { method: 'post', payload: { name: '値' } } |
| 認証ヘッダーを付ける | headers: { Authorization: 'Bearer ' + key } |
| 4xx・5xx でも例外にしない | muteHttpExceptions: true |
| 応答コードを調べる | res.getResponseCode() |
| 本文を文字列で取り出す | res.getContentText() |
| JSON をオブジェクトにする | JSON.parse(res.getContentText()) |
| 応答ヘッダーを調べる | res.getHeaders() |
| 複数の URL をまとめて取得する | UrlFetchApp.fetchAll([{ url: ... }, { url: ... }]) |
| 送る内容を送信せずに確かめる | UrlFetchApp.getRequest(url, params) |
| APIキーを読む | PropertiesService.getScriptProperties().getProperty('API_KEY') |
| 待機する | Utilities.sleep(ミリ秒) |
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「GASで外部APIを呼び出す UrlFetchAppとAPIキーの保存方法」
コピーして使える1本のコード
題材は、備品の一覧を返す架空の API(https://api.example.com/v1/items)です。スプレッドシートに紐づいたスクリプトに貼り、API_BASE と認証ヘッダーの形を、使う API の仕様に合わせて置き換えてください。
// ===== 設定 =====
const API_BASE = 'https://api.example.com/v1'; // 呼び出す API の URL に置き換える
const SHEET_NAME = 'items'; // 書き込み先のシート名
const MAX_TRIES = 4; // 最初の1回を含めた試行回数
/**
* スクリプト プロパティから API キーを読む。
* 未設定のときは、原因が分かるメッセージで止める。
*/
function getApiKey_() {
const key = PropertiesService.getScriptProperties().getProperty('API_KEY');
if (!key) {
throw new Error('スクリプト プロパティ API_KEY が設定されていません。');
}
return key;
}
/**
* 応答コードを見て、429 と 5xx のときだけ待ってから再試行する。
* 2xx なら HTTPResponse を返し、それ以外は応答コードつきのエラーにする。
*/
function fetchWithRetry_(url, params) {
const options = Object.assign({}, params, { muteHttpExceptions: true });
for (let attempt = 1; ; attempt++) {
const res = UrlFetchApp.fetch(url, options);
const code = res.getResponseCode();
if (code >= 200 && code < 300) {
return res;
}
const retryable = code === 429 || code >= 500;
if (!retryable || attempt >= MAX_TRIES) {
throw new Error('HTTP ' + code + ': ' + res.getContentText().slice(0, 200));
}
Utilities.sleep(waitMillis_(res.getHeaders(), attempt));
}
}
/**
* 待ち時間(ミリ秒)を決める。
* Retry-After ヘッダーが秒数で付いていればそれに従い、無ければ 1秒→2秒→4秒 と倍にする。
*/
function waitMillis_(headers, attempt) {
const retryAfter = Number(headers['Retry-After'] || headers['retry-after']);
const ms = retryAfter > 0 ? retryAfter * 1000 : 1000 * Math.pow(2, attempt - 1);
return Math.min(ms, 30000);
}
/**
* 入れ子のオブジェクトを「親.子」という列名の1階層に平らにする。
* 配列は「, 」でつないだ1つの文字列にする。
*/
function flatten_(obj, prefix, out) {
prefix = prefix || '';
out = out || {};
Object.keys(obj).forEach(function (k) {
const v = obj[k];
const key = prefix ? prefix + '.' + k : k;
if (Array.isArray(v)) {
out[key] = v.map(function (x) {
return x !== null && typeof x === 'object' ? JSON.stringify(x) : x;
}).join(', ');
} else if (v !== null && typeof v === 'object') {
flatten_(v, key, out);
} else {
out[key] = v === null || v === undefined ? '' : v;
}
});
return out;
}
/**
* オブジェクトの配列を、1行目が見出しの2次元配列にする。
* 行によって項目が欠けていても、列数がそろうように空文字で埋める。
*/
function toTable_(items) {
const rows = items.map(function (item) { return flatten_(item); });
const headers = [];
rows.forEach(function (row) {
Object.keys(row).forEach(function (k) {
if (headers.indexOf(k) === -1) headers.push(k);
});
});
const body = rows.map(function (row) {
return headers.map(function (h) { return h in row ? row[h] : ''; });
});
return [headers].concat(body);
}
/**
* 外部 API から JSON を取得し、シートへ1回で書き込む。
*/
function importItems() {
const res = fetchWithRetry_(API_BASE + '/items?limit=100', {
method: 'get',
headers: {
Authorization: 'Bearer ' + getApiKey_(),
Accept: 'application/json'
}
});
const data = JSON.parse(res.getContentText());
const items = Array.isArray(data) ? data : data.items;
if (!items || items.length === 0) {
console.log('取得した件数は 0 件でした。');
return;
}
const table = toTable_(items);
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName(SHEET_NAME) || ss.insertSheet(SHEET_NAME);
sheet.clearContents();
sheet.getRange(1, 1, table.length, table[0].length).setValues(table);
console.log(items.length + ' 件を書き込みました。');
}
このコードの流れは次の4段階です。
| 段階 | 関数 | していること |
|---|---|---|
| 1. キーを読む | getApiKey_ |
スクリプト プロパティから読み、無ければ原因の分かる文で止める |
| 2. 呼び出す | fetchWithRetry_ |
応答コードで分岐し、429 と 5xx だけ待って再試行する |
| 3. 表にする | flatten_・toTable_ |
入れ子を「親.子」の列名に平らにし、見出しつきの2次元配列にする |
| 4. 書き込む | importItems |
範囲の行数・列数を配列に合わせ、setValues を1回呼ぶ |
関数名の末尾の _ は、スクリプト エディタの実行メニューに出さない補助関数に付けています。
動きを確かめた結果
UrlFetchApp・Utilities・PropertiesService・SpreadsheetApp を代役のオブジェクトに差し替え、Node.js 22.22.2 で importItems を動かした結果です。API が次の JSON を返す想定にしました。
{"items": [
{"id": 101, "name": "プロジェクター", "room": {"floor": 3, "name": "会議室A"}, "tags": ["映像", "貸出可"], "note": null},
{"id": 102, "name": "ホワイトボード", "room": {"floor": 2, "name": "会議室B"}, "tags": []},
{"id": 103, "name": "延長コード", "room": {"floor": 3, "name": "倉庫"}, "tags": ["電源"], "owner": {"dept": "総務"}}
]}
--- 1) 1回目で 200
fetch の回数: 1 待機(ms): []
ログ: 3 件を書き込みました。
setValues の範囲: 4 行 x 7 列
["id","name","room.floor","room.name","tags","note","owner.dept"]
[101,"プロジェクター",3,"会議室A","映像, 貸出可","",""]
[102,"ホワイトボード",2,"会議室B","","",""]
[103,"延長コード",3,"倉庫","電源","","総務"]
--- 2) 429(Retry-After: 3) → 503 → 200
fetch の回数: 3 待機(ms): [3000,2000]
ログ: 3 件を書き込みました。
--- 3) 500 が続く
fetch の回数: 4 待機(ms): [1000,2000,4000]
エラー: HTTP 500: e4
--- 4) 401(再試行しない)
fetch の回数: 1 待機(ms): []
エラー: HTTP 401: {"error":"invalid api key"}
--- 5) API_KEY が無い
fetch の回数: 0 待機(ms): []
エラー: スクリプト プロパティ API_KEY が設定されていません。
--- 6) 0 件
fetch の回数: 1 待機(ms): []
ログ: 取得した件数は 0 件でした。
- 1) では、3件目にしか無い
owner.deptも列になり、項目の無い行は空文字で埋まっています。行ごとに列数がそろっているので、setValuesにそのまま渡せます。 - 2) では、Retry-After が付いた 429 のあとは 3 秒、ヘッダーの無い 503 のあとは 2 秒待っています。
- 3) では、4回試したところで止まり、最後の応答コードと本文がエラーの文に入ります。
- 4) の 401 は、1回で止まっています。
APIキーをスクリプト プロパティに保存する
画面から保存する手順
Google の公式ガイドに書かれている手順です(画面の表記は英語版のガイドのもの)。
- Apps Script のプロジェクトを開く
- Project Settings(プロジェクトの設定)をクリックする
- Script Properties の下の Add script property をクリックする
- Property にキーの名前(例:
API_KEY)、Value に値を入力する - Save script properties をクリックする
この画面から追加できるのは 50 個までで、それより多い場合はコードから設定すると書かれています。
コードから保存する
/**
* API キーをコードから保存する(1回だけ実行し、実行後は値を消しておく)。
*/
function saveApiKeyOnce() {
PropertiesService.getScriptProperties().setProperty('API_KEY', 'ここにキーを貼る');
}
この関数は、キーを貼って1回実行したら、貼った値をコードから消しておきます。値はプロパティに残るので、以降は getApiKey_ で読み込めます。
プロパティを読み書きするメソッド
| メソッド | 戻り値 | 内容 |
|---|---|---|
getProperty(key) |
String | キーに対応する値を返す。キーが無ければ null |
getProperties() |
Object | すべてのキーと値のコピーを返す |
getKeys() |
String[] | すべてのキーを返す |
setProperty(key, value) |
Properties | 1組を保存する |
setProperties(properties) |
Properties | オブジェクトの中身をまとめて保存する |
setProperties(properties, deleteAllOthers) |
Properties | まとめて保存し、指定すればほかのプロパティを消す |
deleteProperty(key) |
Properties | 1つ消す |
deleteAllProperties() |
Properties | すべて消す |
値はすべて文字列として保存されます。 文字列でない値は自動で文字列に変換されると書かれているので、数値や真偽値を読み出したときは Number(...) や === 'true' で扱います。オブジェクトを入れたいときは JSON.stringify で文字列にしてから保存し、読むときに JSON.parse します。
スクリプト・ユーザー・ドキュメントの3種類の違い
| 種類 | 取得するメソッド | 誰が読めるか | どこに紐づくか | 公式ガイドの用途の例 |
|---|---|---|---|---|
| スクリプト プロパティ | getScriptProperties() |
そのスクリプトのすべての利用者 | スクリプト | 開発者の外部データベースのユーザー名とパスワードのような、アプリ全体の設定 |
| ユーザー プロパティ | getUserProperties() |
いま実行している利用者だけ | スクリプトと利用者の組み合わせ | 単位の表示設定のような、利用者ごとの設定 |
| ドキュメント プロパティ | getDocumentProperties() |
開いているドキュメントのすべての利用者 | スクリプトとドキュメントの組み合わせ | 埋め込んだグラフの元 URL のような、ドキュメントごとのデータ |
- どの種類も、別のスクリプトとは共有されません。
getDocumentProperties()は、スクリプトがアドインとして公開されているか、Google のファイルに紐づいている場合だけ使えます。それ以外では null を返します。
どのプロパティに保存するかの判断表
| 条件 | 選ぶもの |
|---|---|
| チームで1つの APIキーを共有し、誰が実行しても同じキーで呼び出す | スクリプト プロパティ |
| 利用者それぞれが自分の APIキーやトークンを持っている | ユーザー プロパティ |
| スプレッドシートごとに取得先の URL や対象の ID が違う | ドキュメント プロパティ |
| 前回の取得日時など、スクリプト全体で1つあればよい値 | スクリプト プロパティ |
スクリプト プロパティの値は、プロジェクトの設定画面に一覧で表示されます。プロジェクトを開ける人の範囲と、キーを知ってよい人の範囲が合っているかを、保存する前に確かめておくと安心です。
fetchのオプション一覧
UrlFetchApp.fetch(url, params) の params に指定できる項目です。
| 項目 | 型 | 内容 | 既定値 |
|---|---|---|---|
method |
String | HTTP メソッド。get・delete・patch・post・put | get |
headers |
Object | リクエスト ヘッダーのキーと値 | なし |
contentType |
String | 本文の種類。例:application/json、application/xml; charset=utf-8 |
application/x-www-form-urlencoded |
payload |
String など | 送る本文。文字列、バイト配列、Blob、またはオブジェクト。オブジェクトはフォームの項目名と値として扱われる | なし |
muteHttpExceptions |
Boolean | true にすると、応答コードがエラーを示していても例外にせず HTTPResponse を返す | false |
followRedirects |
Boolean | false にするとリダイレクトをたどらず、元の応答を返す | true |
validateHttpsCertificates |
Boolean | false にすると HTTPS の証明書が無効でも続ける | true |
escaping |
Boolean | false にすると URL の予約文字をエスケープしない | true |
- URL の長さは 2,082 文字までと書かれています。
- UrlFetchApp を使うスクリプトには
https://www.googleapis.com/auth/script.external_requestのスコープが必要です。通常は自動で検出され、スコープを明示的に設定している場合だけ自分で追加します。 - リクエストは Google の IP アドレスの範囲から送られます。接続元を制限している API では、その範囲を許可する設定が要ります。
JSONをPOSTする
/**
* JSON を POST で送る。
*/
function createItem() {
const res = fetchWithRetry_(API_BASE + '/items', {
method: 'post',
contentType: 'application/json',
headers: { Authorization: 'Bearer ' + getApiKey_() },
payload: JSON.stringify({ name: 'プロジェクター', room: { floor: 3, name: '会議室A' } })
});
const created = JSON.parse(res.getContentText());
console.log('登録した ID: ' + created.id);
}
JSON を送るときは、contentType と JSON.stringify の2つをそろえます。 payload にオブジェクトをそのまま渡すと、フォームの項目として送られます。
| 送りたい形式 | contentType | payload |
|---|---|---|
| JSON | 'application/json' |
JSON.stringify(obj) |
| フォーム | 指定しない(既定値) | { name: '値', memo: '値' } |
| ファイルつきのフォーム | 指定しない | { name: '値', file: blob } |
送る前に内容を確かめたいときは、UrlFetchApp.getRequest(url, params) を使います。実際には送信せず、送られるはずのリクエストの内容をオブジェクトで返します。
HTTPResponseのメソッド一覧
| メソッド | 戻り値 | 内容 |
|---|---|---|
getResponseCode() |
Integer | HTTP の応答コード(200 など) |
getContentText() |
String | 本文を文字列で返す |
getContentText(charset) |
String | 文字コードを指定して本文を文字列で返す |
getContent() |
Byte[] | 本文をバイト配列で返す |
getBlob() |
Blob | 本文を Blob で返す |
getAs(contentType) |
Blob | 指定した種類に変換した Blob を返す |
getHeaders() |
Object | 応答ヘッダーをキーと値で返す |
getAllHeaders() |
Object | 応答ヘッダーを返す。同じ名前のヘッダーが複数あるものは配列になる |
本文が文字化けするときは、getContentText('Shift_JIS') のように、API が返す文字コードを指定します。画像や PDF のようなバイナリは、getBlob() で受けます。
応答コードで分岐する
muteHttpExceptions: true を付けたうえで、応答コードごとの扱いを決めます。
| 応答コード | 意味 | この記事のコードでの扱い |
|---|---|---|
| 200〜299 | 成功 | HTTPResponse を返す |
| 400 | リクエストの形が合っていない | 再試行せず、本文を表示して止める |
| 401・403 | 認証・権限 | 再試行せず止める。キーの値とヘッダーの形を見直す |
| 404 | URL や ID が見つからない | 再試行せず止める |
| 429 | 呼び出しの回数が多い | 待ってから再試行する |
| 500〜599 | サーバー側の一時的な不調 | 待ってから再試行する |
待ち時間は、応答に Retry-After ヘッダーが秒数で付いていればそれに従い、無ければ 1秒・2秒・4秒と倍に延ばします。1回の待機は 30 秒で頭打ちにしています。スクリプトの実行時間には上限(後述)があるので、試行回数は数回にとどめます。
muteHttpExceptions が効くのは、相手から応答コードが返ってきた場合です。URL の書き方が正しくないなど、応答そのものが得られない場合は fetch が例外を投げるので、呼び出し元を try...catch で囲んで内容を記録します。
function runImport() {
try {
importItems();
} catch (e) {
console.error('取り込みを中止しました: ' + e.message);
throw e; // トリガー実行のときに、実行ログへエラーとして残す
}
}
入れ子のJSONを表に平らにする
API の JSON は、オブジェクトの中にオブジェクトや配列が入っていることがよくあります。シートは行と列の2次元なので、次の決まりで1階層にします。
| JSON の形 | 表での扱い | 例 |
|---|---|---|
| 入れ子のオブジェクト | 「親.子」という列名にする | room.floor、room.name |
| 文字列や数値の配列 | 「, 」でつないで1つのセルに入れる | 映像, 貸出可 |
| オブジェクトの配列 | 要素を JSON の文字列にしてつなぐ | {"k":1}, {"k":2} |
| null・項目なし | 空文字にする | (空のセル) |
setValues に渡す2次元配列は、すべての行の列数が同じである必要があります。 toTable_ は、全行に出てくるキーを集めて見出しを作り、その見出しの順に値を並べるので、項目が欠けた行があっても列数がそろいます。
オブジェクトの配列を別の行に展開したい場合(1件の備品に複数の貸出履歴がある、など)は、親の ID を付けた別の表にして、別のシートへ書き込むと扱いやすくなります。
fetchとfetchAllの使い分け
fetchAll は、リクエストの配列を受け取り、HTTPResponse の配列を返します。配列の要素は、URL の文字列か、url に fetch と同じオプションを加えたオブジェクトです。
/**
* 複数の URL をまとめて取得する。
*/
function importDetails() {
const ids = [101, 102, 103];
const key = getApiKey_();
const requests = ids.map(function (id) {
return {
url: API_BASE + '/items/' + id,
headers: { Authorization: 'Bearer ' + key },
muteHttpExceptions: true
};
});
const responses = UrlFetchApp.fetchAll(requests);
const ok = [];
const ng = [];
responses.forEach(function (res, i) {
if (res.getResponseCode() === 200) {
ok.push(JSON.parse(res.getContentText()));
} else {
ng.push(ids[i] + ' (HTTP ' + res.getResponseCode() + ')');
}
});
console.log('取得できた件数: ' + ok.length + ' / 取得できなかったもの: ' + ng.join(', '));
return ok;
}
代役のオブジェクトで、200・404・200 の3つの応答を返して動かした結果です。
ログ: 取得できた件数: 2 / 取得できなかったもの: 102 (HTTP 404)
muteHttpExceptions は、リクエストごとに付けます。付けておくと、1件が 404 でも全体は止まらず、応答コードで振り分けられます。
| 条件 | 選ぶもの |
|---|---|
| 呼び出す URL が1つ | fetch |
| 前の応答の内容で、次に呼ぶ URL が決まる(次のページの URL が応答に入っている、など) | fetch を順に呼ぶ |
| 呼び出す URL の一覧が先に決まっている(ID ごとの詳細、複数のページ番号) | fetchAll |
| 1件ごとに待機を挟んで再試行したい | fetch(この記事の fetchWithRetry_) |
| まとめて取り、うまくいかなかった分だけあとで取り直したい | fetchAll のあと、残りを fetch で再試行 |
一度に送る件数が多いと、相手の API の回数制限に当たりやすくなります。一覧を 10 件ずつなどに区切って fetchAll に渡し、429 が返ったものを取り直す形にすると、制限の範囲に収めやすくなります。
割り当て上限(公式記載の値)
Google の「Quotas for Google Services」のページに書かれている値です(2026-10-05 閲覧)。
| 項目 | 一般のアカウント | Google Workspace のアカウント |
|---|---|---|
| URL Fetch の呼び出し回数 | 20,000 回/日 | 100,000 回/日 |
| プロパティの読み書き | 50,000 回/日 | 500,000 回/日 |
| 項目 | 上限 |
|---|---|
| スクリプトの実行時間 | 6 分/1回の実行 |
| カスタム関数の実行時間 | 30 秒/1回の実行 |
| 同時実行 | 30/利用者 |
| URL Fetch の応答の大きさ | 50 MB/1回の呼び出し |
| URL Fetch の POST の大きさ | 50 MB/1回の呼び出し |
| URL Fetch のヘッダーの数 | 100/1回の呼び出し |
| URL Fetch のヘッダーの大きさ | 8 KB/1回の呼び出し |
| URL Fetch の URL の長さ | 2 KB/1回の呼び出し |
| プロパティの値の大きさ | 9 KB/1つの値 |
| プロパティの合計の大きさ | 500 KB/1つのプロパティ ストア |
- 1日あたりの割り当ては利用者ごとで、最初のリクエストから 24 時間後にリセットされると書かれています。
- 上限を超えると、スクリプトは例外を投げて実行が止まります。
- プロパティの値は 9 KB までなので、API の応答をまるごと保存する用途には向きません。保存するのは、キーや前回の取得日時のような短い値にします。
実行時間の 6 分に収めるには、取得する件数を1回の実行で扱える量に区切り、どこまで取得したか(ページ番号や最後の ID)をスクリプト プロパティに保存して、次の実行で続きから始める形にします。
似た仕組みとの違いと選び方
| 仕組み | 向き | 向いている用途 |
|---|---|---|
| UrlFetchApp で API を呼び出す(この記事) | GAS から外へ取りに行く | 外部サービスのデータを定期的にシートへ取り込む |
| UrlFetchApp で Webhook の URL へ POST する | GAS から外へ送る | チャットへの通知など、決まった宛先へ知らせを送る |
| ウェブアプリ(doGet・doPost) | 外から GAS へ届く | 外部サービスからの通知を受け取る |
| 条件 | 選ぶもの |
|---|---|
| APIキーやヘッダーが必要 | UrlFetchApp |
| 取得した JSON を加工してから書き込みたい | UrlFetchApp |
| 決まった時刻に自動で取り込みたい | UrlFetchApp + 時間主導型のトリガー |
| 決まった宛先へ知らせを送りたい | Webhook の URL へ POST |
| 外部サービスからの通知を受け取りたい | ウェブアプリ |
確かめて分かったこと
公式のページを開いて照合し、コードを動かして分かった点です。
contentTypeの既定値はapplication/x-www-form-urlencodedです。 JSON を送るつもりでpayloadにJSON.stringifyした文字列だけを渡すと、種類の指定がフォームのままになります。contentType: 'application/json'を必ず書きます。muteHttpExceptionsの既定値は false です。 付けないと、4xx や 5xx のときに例外になり、getResponseCode()まで進みません。getPropertyは、キーが無いとき例外ではなく null を返します。 そのまま'Bearer ' + keyとつなぐとBearer nullという文字列が送られるので、読んだ直後に有無を確かめます(代役での実行 5)。- プロパティの値は文字列になります。 数値のつもりで保存した値も、読み出すと文字列です。
- 型の検査では、
method: 'head'と書くと、型が合わないというエラー(TS2322)になりました。 型定義が受け付けるのは get・delete・patch・post・put で、公式の表に書かれている5種類と一致します。 - 項目の欠けた JSON をそのまま行にすると、行ごとに列数が変わります。 全行のキーを集めて見出しを作る形にすると、3件目だけにある
owner.deptも含めて 7 列にそろいました(代役での実行 1)。
よくある質問
Q. UrlFetchApp とは何ですか?
A. GAS から HTTP と HTTPS のリクエストを送り、応答を受け取るためのサービスです。UrlFetchApp.fetch(url, params) が基本で、戻り値の HTTPResponse から応答コードと本文を取り出します。
Q. スクリプト プロパティとユーザー プロパティの違いは何ですか? A. スクリプト プロパティはそのスクリプトのすべての利用者が読める保存場所、ユーザー プロパティは実行している利用者だけが読める保存場所です。共有の APIキーは前者、利用者ごとのキーは後者に入れます。
Q. API からエラーが返ったとき、内容を確認できないときはどうしますか?
A. muteHttpExceptions: true を付けて、getResponseCode() と getContentText() をログに出します。多くの API は、本文に原因を示す JSON を入れて返します。
Q. 取得した JSON をシートに書き込めないときは何を確かめますか?
A. 範囲の行数・列数と、2次元配列の行数・列数が一致しているかを確かめます。getRange(1, 1, table.length, table[0].length) のように、配列の大きさから範囲を作ると一致します。
Q. fetch と fetchAll の違いは何ですか? A. fetch は1つのリクエストを送って1つの HTTPResponse を返し、fetchAll はリクエストの配列を送って HTTPResponse の配列を返します。URL の一覧が先に決まっているときは fetchAll が向いています。
まとめ
- APIキーはスクリプト プロパティに保存し、
getPropertyで読んだ直後に有無を確かめる - fetch には
muteHttpExceptions: trueを付け、getResponseCode()で分岐する - 再試行は 429 と 5xx だけ。Retry-After があれば従い、無ければ待ち時間を倍に延ばす
- JSON の POST は
contentType: 'application/json'とJSON.stringifyをそろえる - 入れ子の JSON は「親.子」の列名に平らにし、全行の列数をそろえてから
setValuesを1回呼ぶ - URL の一覧が先に決まっていれば fetchAll、前の応答で次が決まるなら fetch
- URL Fetch は一般のアカウントで 20,000 回/日、実行時間は 6 分/回。件数を区切り、続きの位置をプロパティに保存する
参考・出典
いずれも 2026-10-05 に閲覧しました。
- Google Apps Script リファレンス「Class UrlFetchApp」 https://developers.google.com/apps-script/reference/url-fetch/url-fetch-app
- Google Apps Script リファレンス「Class HTTPResponse」 https://developers.google.com/apps-script/reference/url-fetch/http-response
- Google Apps Script ガイド「Properties Service」 https://developers.google.com/apps-script/guides/properties
- Google Apps Script リファレンス「Class PropertiesService」 https://developers.google.com/apps-script/reference/properties/properties-service
- Google Apps Script リファレンス「Class Properties」 https://developers.google.com/apps-script/reference/properties/properties
- Google Apps Script ガイド「Quotas for Google Services」 https://developers.google.com/apps-script/guides/services/quotas
- npm「@types/google-apps-script」(型の検査に使用した型定義) https://www.npmjs.com/package/@types/google-apps-script
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「GASで外部APIを呼び出す UrlFetchAppとAPIキーの保存方法」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。