[Apps Script] API call fails with 404 Not Found, but works from API Explorer

131 views
Skip to first unread message

nana obata

unread,
Jul 7, 2025, 7:24:22 PMJul 7
to Google Ads API and AdWords API Forum
Hello Google Ads API Team,

I am experiencing an issue where API calls from Google Apps Script fail with a 404 error, but the exact same request works perfectly from the API Explorer.

**Summary of the Issue**

-   **API Call:** `customers.listAccessibleCustomers`
-   **Fails From:** Google Apps Script using `UrlFetchApp`. It consistently returns an HTTP 404 error with a generic HTML "Not Found" page.
-   **Succeeds From:** The API Explorer on the official documentation page, using the same Google Account for OAuth and the same Developer Token. This proves that my credentials, developer token, and account permissions are all correct.

**Troubleshooting Steps Already Taken**

-   Verified the request URL is correct: `https://googleads.googleapis.com/v16/customers:listAccessibleCustomers`
-   Confirmed the Google Ads API is enabled in my GCP project.
-   Confirmed the OAuth Consent Screen is in "Testing" mode and my email is added as a test user.
-   Tried changing the `User-Agent` header in the Apps Script request.

Could you please investigate why requests from the Apps Script environment are being rejected? There seems to be an issue specific to requests originating from `UrlFetchApp`.

---

**1. Logs from the FAILED request (from Google Apps Script)**

Please paste the entire execution log from the last Apps Script run here.スクリーンショット 2025-07-08 3.41.01.png


---

**2. The Apps Script Code**

This is the full code used for the test.
// ----------------------------------------------------
// ここにあなたの情報を入力してください
// ----------------------------------------------------
const CLIENT_ID = 'ご自身のクライアントID'; // ★ GCPで取得したあなたのクライアントIDをここに貼り付け
const CLIENT_SECRET = 'ご自身のクライアントシークレット'; // ★ GCPで取得したあなたのクライアントシークレットをここに貼り付け
const CUSTOMER_ID = 'ご自身のGoogle広告ID'; // ★ Google広告のクライアントID (ハイフンなし) をここに貼り付け
const DEVELOPER_TOKEN = 'ご自身の開発者トークン'; // ★ Google広告の「APIセンター」から取得し、ここに貼り付け

// Google Ads APIのバージョン
const API_VERSION = 'v16';
// ----------------------------------------------------


function authenticateGoogleAds() {
const service = getGoogleAdsService();
if (!service.hasAccess()) {
Logger.log('認証が必要です: ' + service.getAuthorizationUrl());
return;
}
Logger.log('すでに認証済みです。');

try {
const accessToken = service.getAccessToken();
Logger.log('\nアクセス可能顧客ID一覧を取得中...');
sendGoogleAdsApiRequest(accessToken, null, `/${API_VERSION}/customers:listAccessibleCustomers`, {});

} catch (e) {
Logger.log('スクリプトの実行中にエラーが発生しました。詳細はログを確認してください。');
}
}

function sendGoogleAdsApiRequest(accessToken, customerId, apiPath, payload) {
const url = `https://googleads.googleapis.com${apiPath}`;
const headers = {
'Authorization': `Bearer ${accessToken}`,
'developer-token': DEVELOPER_TOKEN,
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36'
};
if (customerId) {
headers['login-customer-id'] = customerId;
}
const options = {
'method': 'post',
'contentType': 'application/json',
'headers': headers,
'payload': JSON.stringify(payload),
'muteHttpExceptions': true
};

const response = UrlFetchApp.fetch(url, options);
const responseCode = response.getResponseCode();
const responseBody = response.getContentText();
const responseHeaders = response.getHeaders();
// ★★★ Googleへの問い合わせに必須のリクエストIDを取得 ★★★
const requestId = responseHeaders['request-id'] || responseHeaders['Request-Id'] || 'N/A';

Logger.log(`--- API Response (Path: ${apiPath}) ---`);
Logger.log(`Status Code: ${responseCode}`);
Logger.log(`Request ID: ${requestId}`); // このIDが最も重要です

if (responseCode >= 200 && responseCode < 300) {
Logger.log("Response Body (Success):");
Logger.log(JSON.stringify(JSON.parse(responseBody), null, 2));
return JSON.parse(responseBody);
} else {
Logger.log("Response Body (Error):");
Logger.log(responseBody);
throw new Error(`Google Ads API Request Failed. Code: ${responseCode}, Request ID: ${requestId}`);
}
}

// OAuth2関連の関数 (変更なし)
function getGoogleAdsService() {
return OAuth2.createService('googleAds').setClientId(CLIENT_ID).setClientSecret(CLIENT_SECRET).setScope('https://www.googleapis.com/auth/adwords').setCallbackFunction('authCallback').setPropertyStore(PropertiesService.getUserProperties()).setParam('access_type', 'offline').setParam('prompt', 'consent').setAuthorizationBaseUrl('https://accounts.google.com/o/oauth2/auth').setTokenUrl('https://oauth2.googleapis.com/token');
}
function authCallback(request) {
const service = getGoogleAdsService();
if (service.handleCallback(request)) { return HtmlService.createHtmlOutput('認証に成功しました。'); } else { return HtmlService.createHtmlOutput('認証に失敗しました。'); }
}

---

Thank you for your help.

Google Ads API Forum Advisor

unread,
Jul 7, 2025, 10:01:35 PMJul 7
to 70bat...@gmail.com, adwor...@googlegroups.com

Hi,

Thank you for reaching out to the Google Ads API support team.

Please be noted that the version ‘v16’ is already deprecated and the latest version is v20. I would recommend that you use the latest version in your Apps Script (const API_VERSION = 'v20';).

If you are still facing any issues even after using the updated version, I would recommend that you reach out to the Google Apps Script support team as they are better equipped to check this issue further. 

Kindly note that this support channel specializes in Google Ads API related concerns and technical implementations only and issues related to the Google Apps Script errors are not in our scope.

Thanks,
 
Google Logo Google Ads API Team

Feedback
How was our support today?

rating1    rating2    rating3    rating4    rating5
[2025-07-08 02:00:46Z GMT] This message is in relation to case "ref:!00D1U01174p.!500Ht01rhP4e:ref" (ADR-00317818)



Reply all
Reply to author
Forward
0 new messages