saveapi.org

Resolve a column of links in Google Sheets with Apps Script

A spreadsheet is where many downloader tasks actually live: a marketing team with a column of links, a researcher with a list of posts. Apps Script can call the API directly. This guide is the script, the pacing that keeps you under the rate limit, and the reason it is a menu action rather than a custom function.

Updated

Keep the key out of the sheet

Store it in Script Properties (Project Settings → Script Properties → saveapi_key). A key in a cell travels with every copy and export of the sheet.

The fetch

UrlFetchApp with the Authorization header and muteHttpExceptions so an error response is parsed instead of thrown — the JSON body carries error.code, which is what you want to write into the sheet.

JavaScript
// Apps Script — Extensions → Apps Script
function resolve(link) {
  const key = PropertiesService.getScriptProperties().getProperty("saveapi_key");
  const res = UrlFetchApp.fetch(
    "https://api.saveapi.org/v1/download?url=" + encodeURIComponent(link),
    { headers: { Authorization: "Bearer " + key }, muteHttpExceptions: true },
  );
  return JSON.parse(res.getContentText());
}

Resolve a column

Read the range once, loop, write two cells per row: the media URL and OK, or empty and the error code. The sleep keeps a long column under the key's per-minute limit — 10 on the free tier, 60 on Pro.

JavaScript
// A ustunidagi havolalar → B ustuniga media URL, C ga natija kodi
function resolveColumn() {
  const sheet = SpreadsheetApp.getActiveSheet();
  const rows = sheet.getRange(2, 1, sheet.getLastRow() - 1, 3).getValues();

  rows.forEach((row, i) => {
    if (!row[0] || row[1]) return;              // bo'sh yoki allaqachon yechilgan
    const data = resolve(row[0]);
    const out = data.success
      ? [data.medias[0].url, "OK"]
      : ["", data.error.code];
    sheet.getRange(i + 2, 2, 1, 2).setValues([out]);
    Utilities.sleep(6000);                      // bepul tarif: 10 so'rov/daqiqa
  });
}

Why a menu action, not a custom function

A custom =SAVEAPI(A2) recalculates whenever the sheet does, and each recalculation is a billed request. Run resolving as an action (a menu item or a button), skip rows that already have a result, and the sheet costs credits once per link.

What it costs

1.5 credits per successful resolve, 0.1 for a private or deleted link, nothing for a timeout. A column of 500 links is about 750 credits — inside the free 1,000.

Questions before you build

Can I use a custom function like =SAVEAPI(A2)?
You can, but every recalculation re-runs it and each run is a billed request. The menu-action pattern in this guide costs credits once per link.
Will the script time out on a long column?
Apps Script stops a run after a few minutes. Skip rows that already have a result and run again — the loop picks up where it left off.
Can the sheet download the file too?
UrlFetchApp can fetch the media URL and save it to Drive with DriveApp.createFile, within Apps Script's size limits. For large videos, keep the URL and download elsewhere.

Platform references used here

Other guides

Run this guide with your own key

Key in under a minute. 1,000 free credits, no card, no expiry.

Get a key and try itFull API reference