Vấn đề
Gặp phải lỗi này giống như đâm đầu vào một bức tường gạch. Điều đó có nghĩa là script của bạn đã cạn kiệt hạn mức hàng ngày cho các lệnh gọi UrlFetchApp.fetch(). Google theo dõi các yêu cầu này trong vòng 24 giờ. Đối với tài khoản @gmail.com cá nhân, giới hạn là 20.000 cuộc gọi mỗi ngày. Người dùng Google Workspace nhận được hạn mức lớn hơn là 100.000 cuộc gọi.
Lỗi này thường xuất hiện trong nhật ký thực thi của bạn như sau:
Exception: Service invoked too many times for one day: urlfetch.
Điều này thường xảy ra khi một script chạy bên trong một vòng lặp xử lý hàng trăm hàng trong bảng tính. Nó cũng phổ biến khi các hàm tùy chỉnh (như =GET_DATA()) được đặt trong hàng trăm ô, khiến chúng kích hoạt mỗi khi trang tính tính toán lại.
Bước 1: Triển khai Caching với CacheService
Đừng yêu cầu cùng một dữ liệu hai lần. Nếu script của bạn tìm nạp thông tin không thay đổi hàng phút—như giá cổ phiếu hoặc dự báo thời tiết—hãy lưu trữ nó trong CacheService. Một lệnh gọi API tiêu chuẩn có thể mất 500ms để phản hồi, nhưng đọc từ bộ nhớ tạm (cache) chỉ mất chưa đầy 20ms.
Trước khi tối ưu (Không hiệu quả)
function getPrice(ticker) {
const response = UrlFetchApp.fetch('https://api.example.com/price/' + ticker);
return JSON.parse(response.getContentText()).price;
}
Sau khi tối ưu (Có Caching)
function getPriceWithCache(ticker) {
const cache = CacheService.getScriptCache();
const cachedValue = cache.get(ticker);
if (cachedValue != null) return cachedValue;
const response = UrlFetchApp.fetch('https://api.example.com/price/' + ticker);
const price = JSON.parse(response.getContentText()).price;
// Lưu trữ trong 1 giờ (3600 giây)
cache.put(ticker, price.toString(), 3600);
return price;
}
Bước 2: Gom nhóm các yêu cầu (Batching)
Ngừng gọi API bên trong vòng lặp. Mỗi lệnh gọi fetch() riêng lẻ đều làm tăng chi phí hệ thống và tiêu tốn hạn mức của bạn. Thay vào đó, hãy sử dụng UrlFetchApp.fetchAll(). Phương thức này gửi nhiều yêu cầu song song. Mặc dù mỗi URL vẫn tính vào tổng số hàng ngày của bạn, nhưng fetchAll nhanh hơn đáng kể và giảm nguy cơ script của bạn bị quá thời gian thực thi (timeout).
function fetchMultipleUrls(urlList) {
const requests = urlList.map(url => ({
url: url,
method: 'get',
muteHttpExceptions: true
}));
const responses = UrlFetchApp.fetchAll(requests);
return responses.map(res => res.getContentText());
}
Bước 3: Chuyển logic ra khỏi các hàm tùy chỉnh
Các hàm tùy chỉnh (custom functions) là "kẻ sát nhân thầm lặng" đối với hạn mức. Nếu bạn có 500 ô sử dụng công thức tùy chỉnh, Google có thể tính toán lại tất cả chúng bất cứ khi nào bạn lọc một cột hoặc thay đổi một giá trị duy nhất. Bạn có thể tiêu hết hạn mức 20.000 lệnh gọi chỉ trong vài phút theo cách này.
Cách khắc phục: Thay thế công thức bằng nút đồng bộ hóa thủ công. Tạo một menu tùy chỉnh để xử lý dữ liệu chỉ khi bạn thực sự cần. Điều này giúp bạn kiểm soát việc tiêu thụ hạn mức.
function onOpen() {
SpreadsheetApp.getUi().createMenu('🚀 Công cụ API')
.addItem('Đồng bộ dữ liệu ngay', 'manualSync')
.addToUi();
}
function manualSync() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
const range = sheet.getDataRange();
const values = range.getValues();
// Xử lý tất cả dữ liệu cùng một lúc và ghi lại vào trang tính trong một lần duy nhất
const results = values.map(row => myProcessingLogic(row[0]));
// ... cập nhật trang tính ...
}
Bước 4: Kiểm tra các Trigger theo thời gian
Kiểm tra Bảng điều khiển Apps Script > Kích hoạt (Triggers). Một script chạy mỗi phút và thực hiện 15 lệnh gọi API sẽ tiêu tốn 21.600 yêu cầu mỗi ngày. Con số đó đã vượt quá giới hạn cho tài khoản cá nhân. Hãy tăng khoảng thời gian trigger lên 15 hoặc 30 phút để giúp hạn mức của bạn có không gian "thở".
Cách xác minh việc khắc phục
Google không cung cấp bảng điều khiển hạn mức theo thời gian thực, vì vậy bạn phải chủ động. Theo dõi tab Thực thi (Executions) trong trình chỉnh sửa Apps Script để xem tần suất lỗi urlfetch có giảm xuống hay không. Bạn cũng có thể thêm một cơ chế ghi nhật ký đơn giản để ghi lại số lượng tìm nạp thành công vào một trang tính ẩn. Nếu con số này đi ngang trong khi script của bạn vẫn hoạt động, thì logic caching của bạn đang phát huy tác dụng.
Mẹo chuyên nghiệp
- Sử dụng Mute Exceptions: Luôn đặt
{muteHttpExceptions: true}. Điều này ngăn một lỗi 404 đơn lẻ làm hỏng toàn bộ nhóm yêu cầu của bạn. - Nâng cấp lên Workspace: Nếu dự án của bạn thực sự yêu cầu hơn 50.000 lệnh gọi mỗi ngày, tài khoản Workspace cơ bản là cách dễ nhất để tăng gấp 5 lần giới hạn của bạn.
- Chuyển sang Proxy: Đối với nhu cầu dữ liệu khổng lồ, hãy sử dụng Cloud Function để tổng hợp dữ liệu. Script của bạn thực hiện một lệnh gọi đến proxy và proxy sẽ xử lý hàng trăm yêu cầu con.

