I have a google sheet where there is an Apps Script function called GET_REDIRECT_URL() and it does not work properly. Is there any way to fix this?
The sheet in question
You can access the script in Extensions => Apps Script. For example, in the VSCode Blog url, there is a meta refresh redirect, and the function is unable to extract it, throwing this error:
ERROR: ReferenceError: URL is not defined.
Also, some other URLs throw a different error or fail to fetch.
<!DOCTYPE html>
<html>
<head>
<title>Visual Studio Code Blogs</title>
<meta http-equiv="refresh" content="0; url=/blogs/2025/07/17/copilot-coding-agent">
<meta name="description" content="The latest Visual Studio Code blogs">
<meta name="robots" content="noindex">
<link rel="canonical" href="/blogs/2025/07/17/copilot-coding-agent" />
</head>
</html>
This is my Apps Script implementation:
/**
* Returns the redirect location of a url.
*
* @param {string} input The source URL being redirected.
* @return The destination location/URL.
* @customfunction
*/
function GET_REDIRECT_LOCATION(input) {
// Basic validation
if (!input) return "INVALID_URL";
let url = input.toString().trim();
if (!url || !url.includes(".")) return "INVALID_URL";
// Add https if no protocol
if (!url.startsWith("http")) {
url = "https://" + url;
}
try {
// First try with followRedirects: false to catch HTTP redirects
let response = UrlFetchApp.fetch(url, {
muteHttpExceptions: true,
followRedirects: false
});
let status = response.getResponseCode();
// Check for HTTP redirect (3xx status codes)
if (status >= 300 && status < 400) {
const headers = response.getAllHeaders();
const location = headers.Location || headers.location;
if (location) {
return location;
}
}
// Get the HTML content to check for meta redirects
const content = response.getContentText();
// Check for meta refresh redirect
const metaRefresh = content.match(/content=["']?\d+;\s*url=([^"'\s>]+)["']?/i);
if (metaRefresh && metaRefresh[1]) {
let redirectUrl = metaRefresh[1];
// Handle relative URLs - make them absolute
if (redirectUrl.startsWith('/')) {
const baseUrl = new URL(url);
redirectUrl = baseUrl.protocol + '//' + baseUrl.host + redirectUrl;
}
return redirectUrl;
}
// Check for canonical URL as backup
const canonical = content.match(/<link[^>]*rel=["']canonical["'][^>]*href=["']([^"']+)["']/i);
if (canonical && canonical[1]) {
let canonicalUrl = canonical[1];
// Handle relative URLs
if (canonicalUrl.startsWith('/')) {
const baseUrl = new URL(url);
canonicalUrl = baseUrl.protocol + '//' + baseUrl.host + canonicalUrl;
}
if (canonicalUrl !== url) {
return canonicalUrl;
}
}
return "NO_REDIRECTS_FOUND";
} catch (error) {
return "ERROR: " + error.toString();
}
}
Even after trying to handle this edge case, it still will not work. Does anyone have any solutions?
There was another implementation here, but that one had the same problem.
Add this
class URL {
constructor(str) {
this.protocol = str.startsWith('https://') ? 'https' : 'http';
const l = this.protocol.length + 3;
this.host = str.slice(l, str.indexOf("/", l));
}
}
It could be added anywhere in your Apps Script project, before or after the declaration of the GET_REDIRECT_LOCATION
function, or in a new .gs file.
Note: The above doesn't intend to replicate URL API, it's just a quick and dirty workaround.
Explanation
new URL()
is the constructor of the URL API, which is not available by default in Google Apps Script in the same way that other Web API's aren't available.