tl;dr: Remove the -X POST
flag and add -L
to your curl command.
You've carefully crafted your Google Apps Script web app, published it with access for "Anyone," and written a doPost(e)
function to handle incoming data from a webhook or API. You fire up your terminal to run a quick test with curl, and... you get a 302 Found redirect instead of the "OK" success message you expected. You adjust your curl
command but now get a 405 Method Not Allowed. 😩
Before you start tearing your hair out and filing a bug report (for me to review), let's look at your curl command.
The (3) problems with your Apps Script curl command
You might be using a command like this:
curl -X POST -d '{"key":"value"}' \ https://script.google.com/macros/s/AKf.../exec
- Problem 1: You're not following the redirect that Google Apps Script sends back, which is why you're getting a 302 Found response. Use the
-L
or--location
flag to follow redirects. - Problem 2: The
-X POST
flag is redundant when you're already using the-d
flag. - Problem 3: You might be missing the
Content-Type
header, which is important for Google Apps Script to correctly interpret the data you're sending. Add the-H "Content-Type: application/json"
flag to specify that you're sending JSON data.
Understanding the 302 Redirect Issue
When you send a POST request to a Google Apps Script web app, it doesn't directly execute your script. Instead, it first hits a Google front-end server that responds with a 302 Found status. This response includes a Location header that redirects you to the actual URL where your script will run.
The deployment URL you provided:
https://script.google.com/macros/s/AK.../exec
Becomes this:
https://script.googleusercontent.com/macros/echo?user_content_key=Aeh...cJ&lib=MED...
If you run the curl command with -i
to include the HTTP headers, you'll see an HTTP response like this:
HTTP/2 302 content-type: text/html; charset=UTF-8 access-control-allow-origin: * cache-control: no-cache, no-store, max-age=0, must-revalidate pragma: no-cache expires: Mon, 01 Jan 1990 00:00:00 GMT date: Wed, 09 Jul 2025 15:23:56 GMT location: https://script.googleusercontent.com/macros/echo?user_content_key=Aeh...cJ&lib=MED... x-content-type-options: nosniff x-frame-options: SAMEORIGIN content-security-policy: frame-ancestors 'self' x-xss-protection: 1; mode=block server: GSE alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000 accept-ranges: none vary: Accept-Encoding
Adding the -L
flag to your curl command allows it to follow this redirect:
curl -L -d '{"key":"value"}' \ https://script.google.com/macros/s/AKf.../exec
Note: The change in domain for the redirect from
script.google.com
toscript.googleusercontent.com
is normal and expected. This is an important security measure to separate user generated content from Google applications.
Understanding the 405 Method Not Allowed Issue
If after adding the -L
flag you still get a 405 Method Not Allowed error, it is because historically browsers changed to using GET requests for redirects. Google Apps Script Web Apps also only allow GET requests to the /exec
endpoint after a redirect. You can verify this by checking the HTTP response headers:
HTTP/2 405 cache-control: no-cache, no-store, max-age=0, must-revalidate pragma: no-cache expires: Mon, 01 Jan 1990 00:00:00 GMT date: Wed, 09 Jul 2025 15:23:56 GMT content-type: text/html; charset=utf-8 referrer-policy: origin allow: HEAD, GET x-content-type-options: nosniff x-xss-protection: 1; mode=block server: GSE alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000 accept-ranges: none vary: Accept-Encoding
Which returns HTML with a message like:
Sorry, unable to open the file at this time. Please check the address and try again.
Basically, the curl -X POST
and allow: HEAD, GET
are incompatible. The -X POST
flag is telling curl to use the POST method, while the server is indicating that only HEAD and GET methods are allowed for the requested resource. This mismatch leads to the 405 Method Not Allowed error. To resolve this, simply remove the -X POST
flag from your curl command and let the -d
flag imply the POST method. This way, when the redirect occurs, curl will follow it using the appropriate GET method, and your request should succeed.
Final curl command and example
To summarize, your final curl command should look like this:
curl -L -d '{"foo": "bar"}' \ https://script.google.com/macros/s/AKf.../exec \ -H "Content-Type: application/json"
With a doPost(e)
function in your Google Apps Script that looks like this:
function doPost(e) { return ContentService.createTextOutput( JSON.stringify(e, null, 2) ).setMimeType(ContentService.MimeType.JSON); }
You should now get the following 200 OK response:
{ "contextPath": "", "queryString": "", "contentLength": 14, "postData": { "contents": "{\"foo\": \"bar\"}", "length": 14, "name": "postData", "type": "application/json" }, "parameters": {}, "parameter": {} }
Top comments (0)