GASでBase64エンコード・
デコードする方法
画像をAIに送る、Basic認証のヘッダーを作る、バイナリをJSONに載せる。こうした場面で必ず出てくるのがBase64(バイナリを文字だけで表す変換方式)です。GASではUtilitiesの標準メソッドだけで、追加ライブラリなしに変換できます。
Table of Contents
Base64とは何か・GASで必要になる場面
Base64は、画像やPDFのようなバイナリデータ(人が読めない0と1の並び)を、英数字と記号だけの文字列に置き換える変換方式です。 JSONやHTTPヘッダーは「文字」しか扱えないため、そこにバイナリを載せたいときにBase64が使われます。 GASでは次のような場面で登場します。
画像をAIに送る
Claude APIなどに画像を渡すとき、Base64文字列としてJSONに載せる
Basic認証
「ユーザー名:パスワード」をBase64にしてAuthorizationヘッダーに入れる
HTMLへの埋め込み
data URIとして画像をHTMLメールやWebアプリに直接埋め込む
バイナリの一時保存
ファイルの中身を文字列にしてシートやプロパティに退避する
GASが用意しているのはUtilities.base64Encode()とUtilities.base64Decode()の2つ(+URLセーフ版)です。ブラウザのbtoa/atobはGASでは使えないため、必ずこちらを使います。
文字列をエンコード・デコードする基本
まずは最小の往復(エンコードして元に戻す)です。つまずきやすいのはデコードの戻り値が文字列ではなくバイト配列である点です。文字列に戻すにはUtilities.newBlob()を経由します。
// 文字列をBase64にして、また元に戻す
function base64Basic() {
const text = "こんにちは、GAS";
// 文字コードを明示するのが安全(省略すると環境依存になりやすい)
const encoded = Utilities.base64Encode(text, Utilities.Charset.UTF_8);
Logger.log(encoded); // 例: 44GT44KT44Gr44Gh44Gv44CBR0FT
// デコードすると「バイト配列」が返る。文字列ではない点に注意
const bytes = Utilities.base64Decode(encoded);
// バイト配列 → 文字列 は Blob を経由するのが定番
const decoded = Utilities.newBlob(bytes).getDataAsString("UTF-8");
Logger.log(decoded); // こんにちは、GAS
}日本語を扱うときはUtilities.Charset.UTF_8を第2引数で明示してください。指定を省くと、送信先が期待する文字コードとずれて文字化けの原因になります。 デコード側でgetDataAsString("UTF-8")と揃えるのもセットで覚えておくと安全です。
URLに入れるならbase64EncodeWebSafe
通常のBase64は+と/を含みます。この2文字はURLでは別の意味を持つため、そのままクエリパラメータに入れると壊れます。 URLに載せるときはWebSafe版を使いましょう。
// URLに含めるならWebSafe版を使う
function base64WebSafe() {
// ランダムなバイト列をトークン風の文字列にする例
const raw = Utilities.getUuid() + ":" + new Date().getTime();
// 通常版は「+」「/」を含むため、URLに入れるとエスケープが必要になる
const normal = Utilities.base64Encode(raw, Utilities.Charset.UTF_8);
// WebSafe版は「+」→「-」、「/」→「_」に置き換わる
const webSafe = Utilities.base64EncodeWebSafe(raw, Utilities.Charset.UTF_8);
Logger.log(normal);
Logger.log(webSafe);
// デコードは対応するメソッドを使う(混ぜると壊れる)
const bytes = Utilities.base64DecodeWebSafe(webSafe);
Logger.log(Utilities.newBlob(bytes).getDataAsString("UTF-8"));
}エンコードとデコードは必ず同じ系統を使うのがルールです。WebSafeでエンコードしたものをbase64Decode()に渡すと、元のデータに戻りません。GASをWebアプリとして公開し、URLパラメータでトークンを受け渡す設計では特に注意してください。
Basic認証のヘッダーを組み立てる
社内システムや古めのAPIでよく使われるBasic認証は、「ユーザー名:パスワード」をBase64にした文字列をAuthorizationヘッダーに載せる仕組みです。GASなら1行で作れます。
// Basic認証のヘッダーをBase64で組み立てて外部APIを呼ぶ
function callApiWithBasicAuth() {
const props = PropertiesService.getScriptProperties();
const user = props.getProperty("API_USER");
const pass = props.getProperty("API_PASS");
// Basic認証は「ユーザー名:パスワード」をBase64にした文字列を送る決まり
const token = Utilities.base64Encode(user + ":" + pass, Utilities.Charset.UTF_8);
const res = UrlFetchApp.fetch("https://example.com/api/items", {
method: "get",
headers: { Authorization: "Basic " + token },
muteHttpExceptions: true, // エラーでも例外にせず、コードで判定する
});
const code = res.getResponseCode();
if (code !== 200) {
Logger.log("失敗: " + code + " / " + res.getContentText());
return;
}
const data = JSON.parse(res.getContentText());
Logger.log(data);
}ユーザー名とパスワードはコードに直接書かず、PropertiesService(スクリプトごとの設定保管庫)から読み込みます。Base64は誰でも元に戻せるため、コードに書けば実質そのまま漏れると考えてください。
Drive画像をBase64にしてAIに送る
いまBase64が一番使われるのは、AIへの画像送信です。Claude APIをはじめ多くの生成AI APIは、画像をbase64文字列とMIMEタイプ(データの種類を表す表記)の組で受け取ります。 GoogleドライブのファイルをBlob経由でバイト配列にし、Base64にしてJSONに載せるだけです。
// Driveの画像をBase64にしてClaude APIに送り、内容を説明させる
function describeDriveImage(fileId) {
const apiKey = PropertiesService.getScriptProperties().getProperty("ANTHROPIC_API_KEY");
const blob = DriveApp.getFileById(fileId).getBlob();
const mimeType = blob.getContentType(); // 例: image/png
// getBytes() でバイト配列にしてからBase64文字列へ
const base64 = Utilities.base64Encode(blob.getBytes());
const payload = {
model: "claude-sonnet-5",
max_tokens: 500,
messages: [
{
role: "user",
content: [
{
type: "image",
source: { type: "base64", media_type: mimeType, data: base64 },
},
{ type: "text", text: "この画像に写っているものを日本語で簡潔に説明してください。" },
],
},
],
};
const res = UrlFetchApp.fetch("https://api.anthropic.com/v1/messages", {
method: "post",
contentType: "application/json",
headers: { "x-api-key": apiKey, "anthropic-version": "2023-06-01" },
payload: JSON.stringify(payload),
muteHttpExceptions: true,
});
const json = JSON.parse(res.getContentText());
Logger.log(json.content[0].text);
}ポイントはblob.getContentType()で取得したMIMEタイプを、そのままmedia_typeに渡すことです。ここが実体とずれていると、APIがエラーを返します。 画像から代替テキストを作る具体例はGASで画像をAIで解析しalt属性を自動生成する方法で詳しく解説しています。
data URIでHTMLメールに画像を埋め込む
Base64はdata:image/png;base64,....という形(data URI)にすると、HTMLのimgタグにそのまま埋め込めます。外部URLを用意せずに画像を表示できるのが利点です。
// 画像をdata URIにしてHTMLメールに直接埋め込む
function sendMailWithInlineImage(recipient, fileId) {
const blob = DriveApp.getFileById(fileId).getBlob();
const base64 = Utilities.base64Encode(blob.getBytes());
// data URI は「data:MIMEタイプ;base64,データ」の形式
const dataUri = "data:" + blob.getContentType() + ";base64," + base64;
const html =
"<p>本日のグラフです。</p>" +
'<img src="' + dataUri + '" width="480" alt="売上グラフ">';
MailApp.sendEmail({
to: recipient,
subject: "本日のレポート",
htmlBody: html,
});
}
// 参考: Gmailで確実に表示させたいなら inlineImages を使うほうが安全
function sendMailWithCid(recipient, fileId) {
const blob = DriveApp.getFileById(fileId).getBlob();
MailApp.sendEmail({
to: recipient,
subject: "本日のレポート",
htmlBody: '<img src="cid:graph" width="480" alt="売上グラフ">',
inlineImages: { graph: blob },
});
}ただしメールクライアントによってはdata URIの画像がブロックされます。 Gmail宛てに確実に表示させたい場合は、inlineImagesオプションでBlobを渡し、cid:で参照する方式のほうが安全です。data URIはHtmlServiceで作るWebアプリ側で使うと威力を発揮します。
バイナリをシートに退避して復元する
Base64にすればバイナリも「ただの文字列」になるため、スプレッドシートのセルに保存できます。 小さな画像や署名データを一時的に持っておきたいときに使える手です。 セル1つあたりの上限(約5万文字)を超えないよう、分割して保存します。
// スプレッドシートの添付ファイルをBase64でシートに退避し、あとで復元する
function saveBlobToSheet(fileId) {
const sheet = SpreadsheetApp.getActive().getSheetByName("保管");
const file = DriveApp.getFileById(fileId);
const blob = file.getBlob();
const base64 = Utilities.base64Encode(blob.getBytes());
// 1セルの上限は約5万文字。超える場合は分割して複数セルに入れる
const CHUNK = 45000;
const chunks = [];
for (let i = 0; i < base64.length; i += CHUNK) {
chunks.push(base64.slice(i, i + CHUNK));
}
sheet.appendRow([file.getName(), blob.getContentType(), chunks.length, ...chunks]);
Logger.log(chunks.length + "セルに分割保存しました");
}
function restoreBlobFromRow(rowIndex) {
const sheet = SpreadsheetApp.getActive().getSheetByName("保管");
const row = sheet.getRange(rowIndex, 1, 1, sheet.getLastColumn()).getValues()[0];
const name = row[0];
const mimeType = row[1];
const count = Number(row[2]);
const base64 = row.slice(3, 3 + count).join("");
const bytes = Utilities.base64Decode(base64);
const blob = Utilities.newBlob(bytes, mimeType, name);
DriveApp.createFile(blob);
Logger.log("復元しました: " + name);
}復元側では、分割数を頼りに文字列を結合してからbase64Decode()し、newBlob(bytes, mimeType, name)でファイルに戻します。とはいえ、これは非常用のテクニックです。 通常はDriveにファイルとして保存し、シートにはファイルIDだけを持たせるほうが確実で軽量です。
実務での注意点(サイズ・文字コード・誤解)
1. データは約1.33倍にふくらむ
Base64は3バイトを4文字で表すため、サイズが約1.33倍になります。 3MBの画像は約4MBの文字列になり、GASのメモリと6分の実行時間制限を圧迫します。 大きなファイルはBase64にせず、Blobのまま添付・アップロードするのが基本です。
2. 文字コードは必ず揃える
日本語を含む文字列では、エンコード時のCharsetとデコード時のgetDataAsString()の指定を必ず一致させます。片方だけ省略すると、戻したときに文字化けします。
3. Base64は暗号化ではない
読めない文字列に見えても、誰でも一瞬で元に戻せます。パスワードやAPIキーを「隠す」用途には使えません。 秘密情報はPropertiesServiceに保存し、改ざん検知が必要ならUtilities.computeHmacSignature()など別の仕組みを使ってください。
まとめ
GASのBase64変換はUtilities.base64Encode()とUtilities.base64Decode()の2つが基本で、URLに載せるときだけWebSafe版に切り替えます。 覚えておくべきは3点です。デコードの戻り値はバイト配列なのでBlob経由で文字列に戻すこと、 日本語では文字コードを明示すること、そしてBase64は暗号化ではないこと。 この3つを押さえておけば、AIへの画像送信もBasic認証もつまずかずに実装できます。
よくある質問
Utilities.base64Encode(文字列) を使います。日本語を含む場合は Utilities.base64Encode(文字列, Utilities.Charset.UTF_8) のように文字コードを明示すると安全です。戻すときは Utilities.base64Decode() でバイト配列に戻し、Utilities.newBlob(bytes).getDataAsString() で文字列に変換します。
使われる記号が違います。通常版は「+」と「/」を使い、WebSafe版はそれぞれ「-」と「_」に置き換えます。URLのパラメータやJWT(トークン形式)のようにURLに含める用途ではWebSafe版を使います。デコード側も対応する base64DecodeWebSafe を使う必要があります。
DriveApp.getFileById(id).getBlob().getBytes() でバイト配列を取り出し、Utilities.base64Encode() で文字列にします。Claude APIなど画像を受け取るAPIでは、この文字列と media_type(image/png など)をJSONに載せて送ります。GASのUrlFetchAppはJSONに文字列として載せられるため、追加ライブラリは不要です。
約1.33倍(3バイトが4文字になる)に増えます。GASはBlobをメモリ上で扱うため、数MBを超える画像やPDFをBase64化するとメモリ不足や6分の実行時間制限に近づきます。大きなファイルはそのままBlobとして添付・アップロードし、Base64化は必要な場面に限るのが安全です。
なりません。Base64は「バイナリを文字だけで表す変換」であり、誰でも元に戻せます。パスワードやAPIキーを隠す目的では使えません。GASで秘密情報を扱うときは、コードに直接書かずPropertiesServiceに保存してください。
GAS×AIの業務自動化を
相談する。
画像をAIに解析させる、外部APIと認証付きで連携する、といったGAS開発をご相談いただけます。要件整理から実装・運用までまとめて対応します。