# Python script gets "unsupported grant type" error when getting a token from a Server to Server app

**URL:** <https://devforum.zoom.us/t/python-script-gets-unsupported-grant-type-error-when-getting-a-token-from-a-server-to-server-app/92694>\
**Category:** API and Webhooks\
**Tags:** server-to-server\
**Created:** [August 1, 2023, 2:34am UTC](https://devforum.zoom.us/t/python-script-gets-unsupported-grant-type-error-when-getting-a-token-from-a-server-to-server-app/92694 "2023-08-01T02:34:33Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![gsingh28](https://avatars.discourse-cdn.com/v4/letter/g/5f8ce5/32.png) [@gsingh28](https://devforum.zoom.us/u/gsingh28)\
**Post date:** [August 1, 2023, 2:34am UTC](https://devforum.zoom.us/t/python-script-gets-unsupported-grant-type-error-when-getting-a-token-from-a-server-to-server-app/92694/1 "2023-08-01T02:34:33Z")

</div>

**API Endpoint(s) and/or Zoom API Event(s)**  
_Link the API endpoint(s) and/orZoom API Event(s) you’re working with to help give context._  
/oauth/token

**Description**  
I created a Server to Server app to automate some reports using Python. Unfortunately, my script errors out at step 1, using account credentials to get an access token. Based on some other posts (links below), it seems like the trick is to get the content type right. Not having any luck so far, though. Any of you smart people out there figured out how to get the access token successfully?

Here’s what I’ve tried so far:

- set headers={“Content-Type”: “application/x-www-form-urlencoded; charset=ascii”}
- set headers={“Content-Type”: “application/x-www-form-urlencoded; charset=utf-8”}
- set data = string instead of a dictionary
- set params = {‘grant\_type’: ‘account\_credentials’}
- sending grant\_type and account\_id as params instead of data

**Error?**  
status\_code = 400  
reason = Bad Request  
content = b’{“reason”:“unsupported grant type”,“error”:“unsupported\_grant\_type”}’

**How To Reproduce**  
import requests  
import os  
client\_auth = requests.auth.HTTPBasicAuth(os.getenv(‘zoom\_client\_id’), os.getenv(‘zoom\_client\_secret’))  
v\_token\_raw = requests.post(  
url=‘[https://zoom.us/oauth/token](https://zoom.us/oauth/token)’,  
data={  
‘grant\_type’: ‘account\_credentials’,  
‘account\_id’: os.getenv(‘zoom\_account\_id’)  
},  
auth=client\_auth,  
headers={“Content-Type”: “application/x-www-form-urlencoded”}  
)

**Similar issues that didn’t fix my problem**

- Zoom API Oauth | Error: unsupported\_grant\_type - Zoom Community
- Invalid Grant Type for Oauth app using PHP - #19 by alanj
- [Server to server oauth "unsupported grant type"](https://devforum.zoom.us/t/server-to-server-oauth-unsupported-grant-type/91136)

---

<div class="post-metadata">

**Author:** ![gsingh28](https://avatars.discourse-cdn.com/v4/letter/g/5f8ce5/32.png) [@gsingh28](https://devforum.zoom.us/u/gsingh28)\
**Post date:** [August 1, 2023, 2:58am UTC](https://devforum.zoom.us/t/python-script-gets-unsupported-grant-type-error-when-getting-a-token-from-a-server-to-server-app/92694/2 "2023-08-01T02:58:18Z")

</div>

Not sure if this is helpful, but the [Power shell example](https://developers.zoom.us/docs/internal-apps/s2s-oauth/#powershell) in the developer docs also returns status code 400 for me. Not knowledgeable enough about power shell to get the details of the error response, though.

_request_  
Invoke-WebRequest -UseBasicParsing -Method POST -Uri [https://zoom.us/oauth/token](https://zoom.us/oauth/token) -ContentType ‘application/x-www-form-urlencoded’ -Body @{ grant\_type=‘account\_credentials’; account\_id=removed } -Headers @{ Host=‘[zoom.us](http://zoom.us)’; Authorization=removed }

_returns_  
Invoke-WebRequest : The remote server returned an error: (400) Bad Request.

---

<div class="post-metadata">

**Author:** ![gsingh28](https://avatars.discourse-cdn.com/v4/letter/g/5f8ce5/32.png) [@gsingh28](https://devforum.zoom.us/u/gsingh28)\
**Post date:** [August 1, 2023, 3:17am UTC](https://devforum.zoom.us/t/python-script-gets-unsupported-grant-type-error-when-getting-a-token-from-a-server-to-server-app/92694/3 "2023-08-01T03:17:02Z")

</div>

The [cURL example](https://developers.zoom.us/docs/internal-apps/s2s-oauth/#terminal-command-line-curl-method) also returns “unsupported grant type”.

_request_  
curl -X POST [https://zoom.us/oauth/token](https://zoom.us/oauth/token) -d ‘grant\_type=account\_credentials’ -d ‘account\_id=removed’ -H ‘Host: [zoom.us](http://zoom.us)’ -H ‘Authorization: Basic removed’

_returns_  
{“reason”:“unsupported grant type”,“error”:“unsupported\_grant\_type”}

---

<div class="post-metadata">

**Author:** ![MultiplayerSession](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/multiplayersession/32/66446_2.png) [@MultiplayerSession](https://devforum.zoom.us/u/MultiplayerSession)\
**Post date:** [August 1, 2023, 1:48pm UTC](https://devforum.zoom.us/t/python-script-gets-unsupported-grant-type-error-when-getting-a-token-from-a-server-to-server-app/92694/4 "2023-08-01T13:48:49Z")

</div>

When you tried formatting the `data` as a string, how did you generate that string? It’s supposed to be formatted as a query string, and I’m concerned that the Python [Requests library is being unclear about how it’s interpreting that `data` parameter](https://requests.readthedocs.io/en/latest/api/), which means it can be taking creative liberties.

---

<div class="post-metadata">

**Author:** ![gsingh28](https://avatars.discourse-cdn.com/v4/letter/g/5f8ce5/32.png) [@gsingh28](https://devforum.zoom.us/u/gsingh28)\
**Post date:** [August 1, 2023, 11:27pm UTC](https://devforum.zoom.us/t/python-script-gets-unsupported-grant-type-error-when-getting-a-token-from-a-server-to-server-app/92694/5 "2023-08-01T23:27:39Z")

</div>

I tried hard coding the grant\_type and account\_id in the url, but I’m getting the same error.

base64\_auth\_string = base64.b64encode(f"{os.getenv(‘zoom\_client\_id’)}:{os.getenv(‘zoom\_client\_secret’)}"  
.encode(“ascii”)).decode(“ascii”)  
v\_token\_raw = requests.post(  
url=f"[https://zoom.us/oauth/token/?grant\_type=account\_credentials&account\_id=my](https://zoom.us/oauth/token/?grant_type=account_credentials&account_id=my) account id removed",  
headers={‘Authorization’: f’Basic {base64\_auth\_string}'}  
)

Is that what you meant, @MultiplayerSession ? Since zoom wants a POST request, I thought the grant\_type and account\_id would be passed as application/x-www-form-urlencoded content instead of parameters.

---

<div class="post-metadata">

**Author:** ![gsingh28](https://avatars.discourse-cdn.com/v4/letter/g/5f8ce5/32.png) [@gsingh28](https://devforum.zoom.us/u/gsingh28)\
**Post date:** [August 2, 2023, 12:27am UTC](https://devforum.zoom.us/t/python-script-gets-unsupported-grant-type-error-when-getting-a-token-from-a-server-to-server-app/92694/6 "2023-08-02T00:27:43Z")

</div>

I’m the biggest dummy. 🤦 I clicked on the “OAuth” tile instead of scrolling down to find the " Server-to-Server OAuth" tile in the “Choose your app type” step. I created an actual Server to Server app and now my code gets an access token just fine.

_working code_  
client\_auth = requests.auth.HTTPBasicAuth(os.getenv(‘zoom\_client\_id’), os.getenv(‘zoom\_client\_secret’))  
v\_token\_raw = requests.post(  
url=‘[https://zoom.us/oauth/token](https://zoom.us/oauth/token)’,  
data={  
‘grant\_type’: ‘account\_credentials’,  
‘account\_id’: os.getenv(‘zoom\_account\_id’)  
},  
auth=client\_auth  
)

---

<div class="post-metadata">

**Author:** ![MultiplayerSession](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/multiplayersession/32/66446_2.png) [@MultiplayerSession](https://devforum.zoom.us/u/MultiplayerSession)\
**Post date:** [August 2, 2023, 4:04pm UTC](https://devforum.zoom.us/t/python-script-gets-unsupported-grant-type-error-when-getting-a-token-from-a-server-to-server-app/92694/7 "2023-08-02T16:04:22Z")

</div>

Glad to hear it’s resolved. To cover your previous question, the query string still goes into the body of the request, not the URL. That’s why you’re declaring the `Content-Type` header (to disclose how to interpret the request body). This keeps your account ID out of various log files, since URLs tend to be recorded (but not bodies).

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex016/uploads/zoomdeveloper/original/3X/6/1/614bdd549b610bbaa46ff934617683a02bdaa03c.png) [@system](https://devforum.zoom.us/u/system)\
**Post date:** [August 5, 2024, 7:41am UTC](https://devforum.zoom.us/t/python-script-gets-unsupported-grant-type-error-when-getting-a-token-from-a-server-to-server-app/92694/8 "2024-08-05T07:41:02Z")

</div>

Closed on August 5, 2024, 7:41am UTC

This topic was automatically closed 368 days after the last reply. New replies are no longer allowed.
