DEV Community

Cover image for You're Probably Using curl Wrong with Your Google Apps Script Web App

You're Probably Using curl Wrong with Your Google Apps Script Web App

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 
Enter fullscreen mode Exit fullscreen mode
  • 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 
Enter fullscreen mode Exit fullscreen mode

Becomes this:

https://script.googleusercontent.com/macros/echo?user_content_key=Aeh...cJ&lib=MED... 
Enter fullscreen mode Exit fullscreen mode

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 
Enter fullscreen mode Exit fullscreen mode

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 
Enter fullscreen mode Exit fullscreen mode

Note: The change in domain for the redirect from script.google.com to script.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 
Enter fullscreen mode Exit fullscreen mode

Which returns HTML with a message like:

Sorry, unable to open the file at this time. Please check the address and try again. 
Enter fullscreen mode Exit fullscreen mode

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" 
Enter fullscreen mode Exit fullscreen mode

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); } 
Enter fullscreen mode Exit fullscreen mode

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": {} } 
Enter fullscreen mode Exit fullscreen mode

Top comments (0)