To URL-encode in a spreadsheet, use =ENCODEURL(A2), which exists in Google Sheets and in Excel 2016 or later on Windows. Neither app has a built-in URL decode function, so decoding needs either a short custom function (Apps Script in Sheets, VBA in Excel) or a SUBSTITUTE chain for a few known codes.
This guide gives copy-ready versions of each, plus the mistakes that most often break spreadsheet-built URLs.
What each app supports
| Task | Google Sheets | Excel (Windows, 2016+ / Microsoft 365) | Excel for Mac / web |
|---|---|---|---|
| Encode | ENCODEURL |
ENCODEURL |
Not available (Microsoft) |
| Decode | Apps Script custom function | VBA function | Not built in; use the SUBSTITUTE method |
| Simple decode of a few codes | SUBSTITUTE chain |
SUBSTITUTE chain |
SUBSTITUTE chain |
Microsoft's ENCODEURL page lists support in Excel for Microsoft 365, 2024, 2021, 2019 and 2016, and says the function is not available in Excel for the web or Excel for Mac.
Encoding with ENCODEURL
ENCODEURL takes one text argument and returns it percent-encoded, with spaces as %20. Google's help page shows =ENCODEURL("hello, world!") returning hello%2C%20world%21, and describes the function as encoding text for use in the query string of a URL. Microsoft's own example shows how much it encodes:
=ENCODEURL("http://contoso.sharepoint.com/Finance/Profit and Loss Statement.xlsx")
→ http%3A%2F%2Fcontoso.sharepoint.com%2FFinance%2FProfit%20and%20Loss%20Statement.xlsx
Because it encodes : and /, apply it to values only, never to a finished URL.
Building a search or campaign URL
With a keyword in A2:
="https://example.com/search?q=" & ENCODEURL(A2)
With UTM values in B2:D2 (source, medium, campaign):
="https://example.com/landing?utm_source=" & ENCODEURL(B2)
& "&utm_medium=" & ENCODEURL(C2)
& "&utm_campaign=" & ENCODEURL(D2)
A campaign name such as spring sale becomes spring%20sale. For naming rules that avoid encoding altogether, see UTM parameter encoding mistakes.
Check before you encode
If a column already contains encoded text, running ENCODEURL again turns %20 into %2520. A quick test column flags those rows:
=REGEXMATCH(A2, "%[0-9A-Fa-f]{2}") (Google Sheets)
=ISNUMBER(SEARCH("%2", A2)) (rough check in Excel)
The Excel version only catches codes that start with %2 (space, &, /, + and so on), which covers the common cases. Double URL encoding (%2520) explains how to clean up rows that were encoded twice.
Decoding in Google Sheets with Apps Script
Google's Apps Script guide explains how to add a custom function: open Extensions > Apps Script, paste the code, save, and call it from a cell like a built-in function. This one decodes single cells or whole ranges:
/**
* Decodes URL-encoded (percent-encoded) text.
* @param {string|Array<Array<string>>} input Text or range to decode.
* @param {boolean} plusAsSpace Treat + as a space (default TRUE).
* @return The decoded text.
* @customfunction
*/
function URL_DECODE(input, plusAsSpace) {
if (Array.isArray(input)) return input.map(row => row.map(v => URL_DECODE(v, plusAsSpace)));
if (input === "" || input === null) return "";
let s = String(input);
if (plusAsSpace !== false) s = s.replace(/\+/g, " ");
try { return decodeURIComponent(s); } catch (e) { return "#MALFORMED: " + String(input); }
}
Use it as =URL_DECODE(A2) or =URL_DECODE(A2:A500). Results from a test run of the same code:
| Input | =URL_DECODE(A2) |
=URL_DECODE(A2, FALSE) |
|---|---|---|
caf%C3%A9+au+lait |
café au lait |
café+au+lait |
spring%20sale |
spring sale |
spring sale |
%E2%82%AC5 |
€5 |
€5 |
100% |
#MALFORMED: 100% |
#MALFORMED: 100% |
Notes from Google's documentation: a custom function must finish within 30 seconds, and each call is a separate server request, so one call on a range is faster than thousands of single-cell calls. The + option exists because form-encoded query strings use + for spaces; see %20 vs + in URLs.
Decoding in Excel with VBA
Excel has no decode counterpart to ENCODEURL. On Windows or Mac desktop Excel you can add a VBA function: press Alt+F11, choose Insert > Module, paste the code and save the workbook as .xlsm.
Public Function URL_DECODE(ByVal s As String, Optional ByVal plusAsSpace As Boolean = True) As String
Dim i As Long, cnt As Long, h As String, out As String
Dim buf() As Byte
If plusAsSpace Then s = Replace(s, "+", " ")
ReDim buf(0 To Len(s))
i = 1
Do While i <= Len(s)
h = Mid$(s, i + 1, 2)
If Mid$(s, i, 1) = "%" And Len(h) = 2 And h Like "[0-9A-Fa-f][0-9A-Fa-f]" Then
buf(cnt) = CByte("&H" & h): cnt = cnt + 1
i = i + 3
Else
If cnt > 0 Then out = out & Utf8ToString(buf, cnt): cnt = 0
out = out & Mid$(s, i, 1)
i = i + 1
End If
Loop
If cnt > 0 Then out = out & Utf8ToString(buf, cnt)
URL_DECODE = out
End Function
Private Function Utf8ToString(b() As Byte, ByVal n As Long) As String
Dim i As Long, k As Long, extra As Long, cp As Long, ok As Boolean, out As String
Do While i < n
If b(i) < &H80 Then
cp = b(i): extra = 0
ElseIf b(i) >= &HC0 And b(i) < &HE0 Then
cp = b(i) And &H1F: extra = 1
ElseIf b(i) >= &HE0 And b(i) < &HF0 Then
cp = b(i) And &HF: extra = 2
ElseIf b(i) >= &HF0 And b(i) < &HF8 Then
cp = b(i) And &H7: extra = 3
Else
extra = -1
End If
ok = (extra >= 0 And i + extra <= n - 1)
If ok Then
For k = 1 To extra
If (b(i + k) And &HC0) <> &H80 Then ok = False
Next k
End If
If Not ok Then
out = out & ChrW(&HFFFD&): i = i + 1
Else
For k = 1 To extra
cp = cp * 64 + (b(i + k) And &H3F)
Next k
i = i + extra + 1
If cp > &HFFFF& Then
cp = cp - &H10000
out = out & ChrW(&HD800& + cp \ 1024) & ChrW(&HDC00& + (cp And &H3FF&))
Else
out = out & ChrW(cp)
End If
End If
Loop
Utf8ToString = out
End Function
It collects runs of %XX bytes and converts them as UTF-8, so caf%C3%A9 gives café and %F0%9F%98%80 gives 😀. Invalid sequences such as a lone %C3 become the replacement character �, and a % that is not followed by two hex digits is kept as is. We tested the algorithm with a line-by-line port in Python against the examples above; test the macro on a copy of your data before relying on it.
The no-code option: SUBSTITUTE
For ASCII text with a handful of known codes, nested SUBSTITUTE calls work in both apps and in Excel for the web:
=SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(A2,
"%20"," "), "%2F","/"), "%3A",":"), "%26","&"), "%25","%")
Three rules keep it correct:
- Replace
%25last. Otherwise%2520turns into%20and then into a space, which decodes twice. - Add lowercase variants if needed.
SUBSTITUTEis case-sensitive, and RFC 3986 allows%2fas well as%2F, although it recommends uppercase. - Do not use it for non-ASCII text. Characters such as
éare several bytes (%C3%A9) and need a real UTF-8 decoder.
Common spreadsheet mistakes
- Encoding the whole URL instead of the values.
- Encoding a column twice, producing
%2520. - Copying URLs from an HTML export, which may contain
&instead of&. - Trailing spaces in cells, which become
%20at the end of a parameter. Wrap inputs inTRIM(). - Mixed case in UTM values. Google Analytics 4 treats
Emailandemailas different values; useLOWER()before encoding.
To check a finished URL from your sheet, paste it into the URL parser, which lists every parameter decoded and flags double encoding. For one-off strings, the URL encode and decode operations on the universal encoder decoder give the same result as the formulas above.
Frequently asked questions
Is there a URL decode function in Google Sheets?
No built-in one. Google Sheets has ENCODEURL for encoding, but decoding needs a custom function written in Apps Script, such as the URL_DECODE function in this guide, or a chain of SUBSTITUTE calls for a few known codes.
Why does ENCODEURL not work in Excel for Mac or Excel for the web?
Microsoft's documentation says ENCODEURL is not available in Excel for the web, and that on Mac it may appear in the function list but relies on Windows operating system features and will not return results. It is supported in Excel 2016 and later and Microsoft 365 on Windows.
Should I run ENCODEURL on a whole URL?
No. It encodes the colon and slashes too, so https://example.com becomes https%3A%2F%2Fexample.com. Encode only the parameter values and join them to the fixed part of the URL with &.
Split a URL into scheme, host, path, query and fragment, and decode every parameter.
Open the URL ParserSources
- support.microsoft.com/en-us/office/encodeurl-function-07c7fb90-7c60-4bff-8687-fac50fe33d0e
- support.google.com/docs/answer/9199778
- developers.google.com/apps-script/guides/sheets/functions
- developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent
- rfc-editor.org/rfc/rfc3986#section-2.1