Recall.ai has raised a $38M series B!

More resources

Filter by category

View all

Tutorials

Best Practices

Tutorials

Deep Dive

Zoom Developer Forum

.avif) Google Meet Developer Forum

Microsoft Teams Developer Forum

Announcements

Thank you! Your submission has been received!

Oops! Something went wrong while submitting the form.

\ A guide to programmatic screen capture on macOS\ \ Deep Dive](/content/blog/macos-screencapture-api/index.html)

\ Joining multiple simultaneous meetings through the Zoom SDK\ \ Zoom Developer Forum](/content/blog/zoom-sdk-simultaneous-meeting-limitations/index.html)

\ How to get transcripts from Microsoft Teams\ \ Tutorials](/content/blog/how-to-get-transcripts-from-microsoft-teams/index.html)

\ How to Get Recordings and Transcripts from Slack Huddles\ \ Tutorials](/content/blog/get-recordings-and-transcripts-from-slack-huddles-api/index.html)

\ Understanding the Zoom On Behalf Of (OBF) Token\ \ Deep Dive](/content/blog/zoom-obf/index.html)

\ What is a meeting bot?\ \ Deep Dive](/content/blog/what-is-a-meeting-bot/index.html)

\ Zoom SDK Credentials\ \ Deep Dive](/content/blog/zoom-sdk-credentials/index.html)

\ What is a Zoom Access Key (ZAK) token?\ \ Deep Dive](/content/blog/what-is-a-zoom-access-key-zak-token/index.html)

\ How WebSockets cost us $1M on our AWS bill\ \ Deep Dive](/content/blog/how-websockets-cost-us-1m-on-our-aws-bill/index.html)

\ The fix for a segfault that never shipped\ \ Deep Dive](/content/blog/the-fix-for-a-segfault-that-never-shipped/index.html)

\ Postgres Postmaster does not scale\ \ Deep Dive](/content/blog/postgres-postmaster-does-not-scale/index.html)

\ How to access audio streams in the Zoom Web SDK?\ \ Zoom Developer Forum](/content/blog/how-to-access-audio-streams-in-the-zoom-web-sdk/index.html)

\ How to determine if audio is connected on the Zoom Web SDK?\ \ Zoom Developer Forum](/content/blog/how-to-determine-if-audio-is-connected-on-the-zoom-web-sdk/index.html)

\ Recall.ai Series B: The API for Meeting Recording\ \ Announcements](/content/blog/recall-ai-series-b-the-api-for-meeting-recording/index.html)

\ How to build a Microsoft Teams Bot\ \ Tutorials](/content/blog/how-to-build-a-microsoft-teams-bot/index.html)

\ What is the Google Meet Media API?\ \ Best Practices](/content/blog/what-is-the-google-meet-media-api/index.html)

\ Postgres LISTEN/NOTIFY does not scale\ \ Deep Dive](/content/blog/postgres-listen-notify-does-not-scale/index.html)

\ Code Walkthrough: Generating Meeting Action Items With Recall.ai\ \ Tutorials](/content/blog/generating-meeting-action-items-with-recall-ai/index.html)

\ What are speaker labels and how to obtain them\ \ Tutorials](/content/blog/speaker-labels-and-names-explained/index.html)

\ 7 APIs to get Zoom transcripts: A comprehensive guide\ \ Best Practices](/content/blog/7-apis-to-get-zoom-transcripts-a-comprehensive-guide/index.html)

\ How to get transcripts from Zoom\ \ Tutorials](/content/blog/how-to-get-transcripts-from-zoom/index.html)

\ How to record Microsoft Teams\ \ Tutorials](/content/blog/how-to-get-recordings-from-microsoft-teams/index.html)

\ New Recall.ai Pricing for 2026: $0.50 per Hour of Meeting Recording\ \ Announcements](/content/blog/new-recall-ai-pricing-for-2026/index.html)

\ Open source Microsoft Teams recording software\ \ Microsoft Teams Developer Forum](/content/blog/microsoft-teams-recording-software-open-source/index.html)

\ How to pick a meeting note taker\ \ Best Practices](/content/blog/how-to-pick-a-meeting-note-taker/index.html)

\ How to Get a Recording from the Google Meet API\ \ Best Practices](/content/blog/how-to-get-a-recording-from-the-google-meet-api/index.html)

\ How to get Google Meet transcripts programmatically\ \ Best Practices](/content/blog/how-to-get-transcripts-from-google-meet-developer-edition/index.html)

\ What is Zoom RTMS?\ \ Best Practices](/content/blog/what-is-zoom-rtms/index.html)

\ How to build a desktop recording app (Like Granola)\ \ Tutorials](/content/blog/how-to-build-a-desktop-recording-app/index.html)

\ Speaker Diarization: What it is and how to get diarized transcripts\ \ Best Practices](/content/blog/speaker-diarization/index.html)

\ Understanding Zoom RTMS Behavior and Its Constraints\ \ Best Practices](/content/blog/understanding-zoom-rtms-behavior-and-its-constraints/index.html)

\ How to build a meeting notetaker\ \ Tutorials](/content/blog/how-to-build-a-meeting-notetaker/index.html)

\ How to build a meeting bot \ \ Tutorials](/content/blog/how-to-build-a-meeting-bot/index.html)

\ When to build a Microsoft Teams bot with Puppeteer\ \ Microsoft Teams Developer Forum](/content/blog/puppeteer-microsoft-teams-bot/index.html)

\ How to join a Zoom meeting using the Zoom Meeting SDK\ \ Zoom Developer Forum](/content/blog/how-to-join-a-zoom-meeting-using-the-zoom-meeting-sdk/index.html)

\ Microsoft Teams open source bot\ \ Microsoft Teams Developer Forum](/content/blog/microsoft-teams-open-source-bot/index.html)

\ How to Build a Google Meet Bot from Scratch\ \ Tutorials](/content/blog/how-i-built-an-in-house-google-meet-bot/index.html)

.avif)\ Is there open source Google Meet recording software?\ \ Google Meet Developer Forum](/content/blog/is-there-open-source-google-meet-recording-software/index.html)

.avif)\ Puppeteer Google Meet Bot\ \ Google Meet Developer Forum](/content/blog/puppeteer-google-meet-bot/index.html)

\ Zoom recording software open source\ \ Zoom Developer Forum](/content/blog/zoom-recording-software-open-source/index.html)

\ How to build a Chrome recording extension using tabCapture API\ \ Tutorials](/content/blog/how-to-build-a-chrome-recording-extension/index.html)

\ Zoom Signature Invalid\ \ Zoom Developer Forum](/content/blog/zoom-signature-invalid/index.html)

\ How to get automatic recordings from a Zoom bot\ \ Zoom Developer Forum](/content/blog/zoom-bot-automatic-recording/index.html)

\ Retrieving participant names through the Zoom SDK\ \ Zoom Developer Forum](/content/blog/zoom-sdk-retrieving-participant-names/index.html)

\ How to Access Live Transcription Data from Zoom Web SDK (Component View)\ \ Zoom Developer Forum](/content/blog/how-to-access-live-transcription-data-from-zoom-web-sdk-component-view/index.html)

\ How to build a Zoom bot from scratch\ \ Tutorials](/content/blog/how-to-build-a-zoom-bot/index.html)

\ Create a Google Meet Programmatically\ \ Tutorials](/content/blog/create-a-google-meet-programmatically/index.html)

\ How to join Zoom using Puppeteer\ \ Zoom Developer Forum](/content/blog/how-to-join-zoom-using-puppeteer/index.html)

\ Handling Zoom SDK recording permissions\ \ Zoom Developer Forum](/content/blog/zoom-sdk-recording-permissions/index.html)

\ How to Enable a Zoom Bot to Skip the Waiting Room\ \ Zoom Developer Forum](/content/blog/zoom-bot-skip-waiting-room/index.html)

\ How do I sync audio and video when processing raw audio/video from the Zoom SDK?\ \ Zoom Developer Forum](/content/blog/how-do-i-sync-audio-and-video-when-processing-raw-audio-video-from-the-zoom-sdk/index.html)

\ Fixing DLL warnings in the Zoom Windows Meeting SDK\ \ Zoom Developer Forum](/content/blog/fixing-dll-warnings-in-the-zoom-windows-meeting-sdk/index.html)

\ Zoom join tokens for local recording\ \ Best Practices](/content/blog/zoom-join-tokens-for-local-recording/index.html)

\ How to get recordings from Zoom using a Zoom recording bot API\ \ Tutorials](/content/blog/how-to-get-recordings-from-zoom/index.html)

\ How to manage ZAK Tokens for Zoom bots\ \ Zoom Developer Forum](/content/blog/how-to-manage-zak-tokens-for-zoom-bots/index.html)

\ How to build a Zoom notetaker\ \ Tutorials](/content/blog/how-to-build-a-zoom-notetaker/index.html)

\ Recall.ai Announces Participant Emails\ \ Announcements](/content/blog/recall-ai-announces-participant-emails/index.html)

\ How often should I expect to receive the Zoom recording completed webhook for a single meeting?\ \ Zoom Developer Forum](/content/blog/how-often-should-i-expect-to-receive-the-zoom-recording-completed-webhook-for-a-single-meeting/index.html)

\ Why are waiting rooms causing issues with the Zoom Web Meeting SDK?\ \ Zoom Developer Forum](/content/blog/why-are-waiting-rooms-causing-issues-with-the-zoom-web-meeting-sdk/index.html)

\ Why is my Zoom recording completed webhook so delayed?\ \ Zoom Developer Forum](/content/blog/why-is-my-zoom-recording-completed-webhook-so-delayed/index.html)

\ Why aren't transcription webhooks firing for my Zoom meetings?\ \ Zoom Developer Forum](/content/blog/why-arent-transcription-webhooks-firing-for-my-zoom-meetings/index.html)

\ How do I track participants across Zoom breakout rooms?\ \ Zoom Developer Forum](/content/blog/how-do-i-track-participants-across-zoom-breakout-rooms/index.html)

\ Can I identify meeting participants by email on Zoom?\ \ Zoom Developer Forum](/content/blog/can-i-identify-meeting-participants-by-email-on-zoom/index.html)

\ How do I capture participant data in real time on Zoom?\ \ Zoom Developer Forum](/content/blog/how-do-i-capture-participant-data-in-real-time-on-zoom/index.html)

\ Tracking persistent Zoom meeting ID's for participants who leave and rejoin\ \ Zoom Developer Forum](/content/blog/tracking-persistent-zoom-meeting-ids-for-participants-who-leave-and-rejoin/index.html)

\ Debugging issues with automatic cloud recording\ \ Zoom Developer Forum](/content/blog/debugging-issues-with-automatic-cloud-recording/index.html)

\ Tracking Zoom meetings when using Zoom PMI\ \ Zoom Developer Forum](/content/blog/tracking-zoom-meetings-when-using-zoom-pmi/index.html)

\ Encoding raw video from the Zoom SDK to MP4\ \ Zoom Developer Forum](/content/blog/encoding-raw-video-from-the-zoom-sdk/index.html)

\ Handling crashes in the Zoom Windows Meeting SDK\ \ Zoom Developer Forum](/content/blog/handling-crashes-in-the-zoom-windows-meeting-sdk/index.html)

\ Encoding raw video frames from the Zoom SDK to JPEG\ \ Zoom Developer Forum](/content/blog/decoding-raw-video-frames-from-the-zoom-sdk/index.html)

\ Recording meetings without a local recording token\ \ Zoom Developer Forum](/content/blog/recording-meetings-without-a-local-recording-token/index.html)

\ Resolving intermittent errors while downloading Zoom transcripts\ \ Zoom Developer Forum](/content/blog/resolving-intermittent-errors-while-downloading-zoom-transcripts/index.html)

\ Applying account-level settings to meetings created via the Zoom API\ \ Zoom Developer Forum](/content/blog/applying-account-level-settings-to-meetings-created-via-the-zoom-api/index.html)

\ Why can't my bot join meetings hosted by people outside of my Zoom organization?\ \ Zoom Developer Forum](/content/blog/why-cant-my-bot-join-meetings-hosted-by-people-outside-of-my-zoom-organization/index.html)

\ Zoom Cloud Recording API: Transcript Tutorial, Common Pitfalls, and Workarounds\ \ Tutorials](/content/blog/zoom-transcript-api/index.html)

\ Zoom Meeting Bots: What They Are and Solutions\ \ Deep Dive](/content/blog/zoom-bots/index.html)

\ Can I access gallery view video on the Linux SDK?\ \ Zoom Developer Forum](/content/blog/can-i-access-gallery-view-video-on-the-linux-sdk/index.html)

\ How to access the Zoom Archive Files API\ \ Zoom Developer Forum](/content/blog/how-to-access-the-zoom-archive-files-api/index.html)

\ Resolving Web SDK local recording errors\ \ Zoom Developer Forum](/content/blog/resolving-web-sdk-local-recording-errors/index.html)

\ How to resolve permissions errors with the Zoom Users API\ \ Zoom Developer Forum](/content/blog/how-to-resolve-permissions-errors-with-the-zoom-users-api/index.html)

\ How to track participant name changes in breakout rooms\ \ Zoom Developer Forum](/content/blog/how-to-track-participant-name-changes-in-breakout-rooms/index.html)

\ Why is the transcript.completed webhook not firing?\ \ Zoom Developer Forum](/content/blog/zoom-sdk-webhook-not-firing/index.html)

\ Debugging Zoom SDK failed video capture\ \ Zoom Developer Forum](/content/blog/zoom-sdk-debugging-video-capture/index.html)

\ Capturing video and audio streams through the Zoom SDK\ \ Zoom Developer Forum](/content/blog/zoom-sdk-receiving-video-streams/index.html)

\ Can you suppress the Zoom recording consent prompt through the SDK?\ \ Zoom Developer Forum](/content/blog/zoom-sdk-suppressing-consent-prompt/index.html)

\ How to stream video to a meeting through the Zoom SDK\ \ Zoom Developer Forum](/content/blog/zoom-sdk-streaming-video-to-meeting/index.html)

\ Sending chat messages through the Zoom SDK\ \ Zoom Developer Forum](/content/blog/zoom-sdk-sending-chat-messages/index.html)

\ Handling Zoom app OAuth redirect URL requirements\ \ Zoom Developer Forum](/content/blog/zoom-app-oauth-redirect-url-requirement/index.html)

\ Debugging missing Zoom transcription webhooks\ \ Zoom Developer Forum](/content/blog/zoom-sdk-missing-transcription-webhooks/index.html)

\ Handling Zoom SDK recording compliance requirements\ \ Zoom Developer Forum](/content/blog/zoom-sdk-compliance-requirements/index.html)

\ Handling Zoom app verification\ \ Zoom Developer Forum](/content/blog/zoom-app-domain-verification/index.html)

\ How to join registration-required meetings with a Zoom bot\ \ Zoom Developer Forum](/content/blog/zoom-sdk-joining-registration-required-meetings/index.html)

\ How to use a Zoom bot to join meetings without passcodes\ \ Zoom Developer Forum](/content/blog/zoom-sdk-joining-meetings-without-passcodes/index.html)

\ Debugging stuck Zoom SDK bots\ \ Zoom Developer Forum](/content/blog/zoom-sdk-docker-issues/index.html)

\ How to create a voice agent to send to Zoom meetings\ \ Zoom Developer Forum](/content/blog/zoom-sdk-ai-voice-agent/index.html)

\ How to capture Zoom audio and video with a meeting bot\ \ Zoom Developer Forum](/content/blog/create-audio-video-capture-bots/index.html)

\ How to transcribe a Zoom meeting in real time\ \ Zoom Developer Forum](/content/blog/accessing-real-time-transcription-api/index.html)

\ How to receive raw video from the Zoom SDK\ \ Zoom Developer Forum](/content/blog/accessing-host-video-stream/index.html)

\ Announcing the Recall.ai and Speechmatics Integration\ \ Announcements](/content/blog/announcing-the-recall-ai-and-speechmatics-integration/index.html)

\ Can I access raw audio data using the Zoom Web SDK?\ \ Zoom Developer Forum](/content/blog/can-i-access-raw-audio-data-using-the-zoom-web-sdk/index.html)

Go To Blog

Tutorials

Zoom Cloud Recording API: Transcript Tutorial, Common Pitfalls, and Workarounds

Updated at:

October 24, 2025

Written By:

Vivek Sahu

Table of Contents

Introduction

Zoom provides a platform for video conferencing, but there are often scenarios where we need to access the transcripts of a recorded meeting. This could be useful for various purposes, such as sharing meeting notes over email, translating the meeting content into multiple languages, or analyzing and summarizing the discussion using advanced language models.

Fortunately, Zoom offers APIs that allow developers to retrieve transcripts for the recorded meetings, albeit with some limitations. However, the Zoom official documentation does not provide a detailed guide for using these APIs, or the caveats they come with.

In this article, we will explore the process of accessing these transcripts via Zoom's Cloud Recording API. We will cover the necessary setup, including creating a Zoom App and obtaining the required credentials, as well as providing a Python code example that demonstrates how to interact with the Zoom API to retrieve the meeting transcripts. We will also look into its limitations, some workarounds that can be employed, and quickly touch on a few alternatives.

Note that while we are using Python here, this can be easily translated into other languages with ease. At the heart of it, all we are doing is calling Zoom APIs. If you want to build a Zoom bot yourself, you can either start from scratch with our blog on how to build a zoom bot or check out our Zoom transcript API which works in just a few lines of code ( tutorial on how to get transcripts from Zoom).

Overview of steps

We will simply do 3 things:

Brief on Zoom Apps and OAuth2

Zoom employs the OAuth 2.0 protocol for authorizing access to its APIs. OAuth is an industry-standard authorization mechanism that allows applications to securely access resources on behalf of a user or service account without exposing sensitive credentials like passwords.

To access the Zoom APIs, you need to create a Server-to-Server OAuth app within the Zoom App Marketplace. This type of application is suitable for machine-to-machine communication, which is precisely what we need in this case.

Pre-requisites

Create a Server-to-Server OAuth App

Follow these steps:

1. Let's go to the Zoom App Marketplace. Click on Develop and then click on Server-to-Server App.

2. Give a name to your app. In this example, we've called it MyTranscriptionApp. You can give it your own name. Click on Create.

3. You should now be in the App Credentials section: Notice your Account ID, Client ID, and Client Secret in the App Credentials. These client values are specific to your app. When we make Zoom API calls later, we will use these.

4. Provide details in the Information section.

5. Next jump to Scopes. Here, we will be defining the scopes to which this app's tokens have access to. This in turn defines which APIs can be called using the token.

In this tutorial, we'll be using the following endpoints:

That means we'll need the following scopes, which Zoom mentions in the documentation for those endpoints:

  • cloud_recording:read:list_user_recordings:admin
  • cloud_recording:read:list_recording_files:admin

6. Next, go to the Activation section and click Activate your app. Your app won't provide the access_tokens without this step.

Before Activation:

After Activation:

Start and complete a meeting

Start a Zoom meeting. Ensure that you have enabled Cloud recording by expanding Options, checking the option for Automatically record meeting, and selecting the In the cloud radio button.

Join the meeting alone, or add more people. Talk for a couple of seconds during the meeting, and then end the meeting.

It will take a few minutes for the recording to show up as Zoom needs to process it. For this article, we'll monitor the Recordings Tab for the recording.

You can also use the recording.transcript_completed webhook event to be notified when the recording transcript is available.

Write code to fetch transcripts

Now that we've set up our Server-to-Server OAuth App and completed a meeting, let's write code to fetch details from the Zoom API.

In this section, we'll create a Zoom SDK Python Client that can interact with the Zoom API to fetch transcripts.

Create a Zoom SDK Client

We'll create a simple Zoom SDK Client.

1$ mkdir my-zoom-sdk-client

2$ cd my-zoom-sdk-client

3$ python3 -m venv venv

4$ source venv/bin/activate

5$ echo"requests" >> requirements.txt

6$ pip install -r requirements.txt

Create a file called main.py and copy the following code:

1"""

2MyZoomSDKClient

3"""

4import requests

5

6

7classMyZoomSDKClient:

8

9# Initialize the client with account_id, client_id, and client_secret

10def__init__(self, client_id, client_secret, account_id):

11 self.client_id = client_id

12 self.client_secret = client_secret

13 self.account_id = account_id

14 self.access_token = None

15

16# Generate a new access token only if one does not exist, or if the user explicitly asks to generate

17# (using 'force=True' means generating a new token)

18defget_access_token(self, force=False):

19if self.access_token andnot force:

20return self.access_token

21

22 access_token_uri = "https://zoom.us/oauth/token"

23 data = {

24"grant_type": "account_credentials",

25"account_id": self.account_id,

26"client_id": self.client_id,

27"client_secret": self.client_secret

28 }

29 response = self._make_request(access_token_uri, data=data, method='POST')

30return response.json()["access_token"]

31

32def_make_request(self, uri, headers=None, method='GET', data=None):

33try:

34if method == 'POST':

35 response = requests.post(uri, headers=headers, data=data)

36else:

37 response = requests.get(uri, headers=headers)

38

39if response.status_code // 100 != 2:

40raise Exception('Invalid response from Zoom API. Please try again later.')

41return response

42except Exception as e:

43raise Exception('Invalid response from Zoom API. Please try again later. Error Message: ' + str(e))

... See all 43 lines

  • __init__ simply initializes our client with the account_id, client_id and client_secret.(Remember we saw these earlier in Step 3 in the Create a Server-to-Server OAuth App section?)
  • _make_request is just a utility function that allows us to call any REST APIs.
  • get_access_token generates a new access token by calling the Zoom OAuth API. force is a simple maneuver to ensure a new access_token is generated instead of reusing the earlier access_token. access_tokens expire after a certain time.

Let's see if all works well.

1$ python3

2>>> CLIENT_ID=''# Put your Client ID

3>>> CLIENT_SECRET=''# Put your CLIENT_SECRET

4>>> ACCOUNT_ID=''# Put your ACCOUNT_ID

5>>> from main import MyZoomSDKClient

6>>> client = MyZoomSDKClient(CLIENT_ID, CLIENT_SECRET, ACCOUNT_ID)

7>>> access_token = client.get_access_token()

8>>> print(access_token)

9>>> exit()

List all meetings

We'll modify the code to access the List Recordings API.

1GET /users/{userId}/recordings

Update main.py to call List Meetings and return parsed data. Use the following code:

1#...

2# Generate authorization header using access_token

3defget_authorization_header(self):

4return { "Authorization": f"Bearer {self.get_access_token()}" }

5

6# List id and topic of all my meetings

7deflist_my_meetings(self):

8 list_meetings_uri = "https://api.zoom.us/v2/users/me/recordings"

9 headers = self.get_authorization_header()

10

11 response = self._make_request(list_meetings_uri, headers=headers)

12return [(x['id'], x['topic']) for x in response.json()['meetings']]

13#...

... See all 13 lines

Let's see it in action:

1$ python3

2>>> CLIENT_ID=''# Put your Client ID

3>>> CLIENT_SECRET=''# Put your CLIENT_SECRET

4>>> ACCOUNT_ID=''# Put your ACCOUNT_ID

5>>> from main import MyZoomSDKClient

6>>> client = MyZoomSDKClient(CLIENT_ID, CLIENT_SECRET, ACCOUNT_ID)

7>>> meetings = client.list_my_meetings()

8>>> print(meetings)

9>>> exit()

Get Meeting Details

Let's modify the code to access the Get Recording API.

1GET "/meetings/{meetingId}/recordings"

Update main.py to add the following function:

1#...

2# Get meeting details by ID

3defget_meeting_details(self, meeting_id):

4if meeting_id in self.meetings:

5return self.meetings[meeting_id]

6

7 meeting_details_url = f"https://api.zoom.us/v2/meetings/{meeting\_id}/recordings"

8 headers = self.get_authorization_header()

9

10 self.meetings[meeting_id] = self._make_request(meeting_details_url, headers=headers).json()

11return self.meetings[meeting_id]

12#...

... See all 12 lines

Also, add this new property to the client:

1classMyZoomSDKClient:

2

3# Initialize the client with account_id, client_id, and client_secret

4def__init__(self, client_id, client_secret, account_id):

5# ...

6 self.meetings = {}

Let's run this code to get our meeting details:

1$ python3

2>>> CLIENT_ID=''# Put your Client ID

3>>> CLIENT_SECRET=''# Put your CLIENT_SECRET

4>>> ACCOUNT_ID=''# Put your ACCOUNT_ID

5>>> from main import MyZoomSDKClient

6>>> client = MyZoomSDKClient(CLIENT_ID, CLIENT_SECRET, ACCOUNT_ID)

7>>> meetings = client.list_my_meetings()

8>>> my_meeting = client.get_meeting_details(meetings[0][0])

9>>> print(my_meeting)

10>>> exit()

Get Transcriptions

Finally, let's add the following code to fetch the transcripts. Transcripts are available as part of the Get Recording API. The API response contains a recording_files property which contains all the download_urls for video recordings, audio recordings, transcripts, and more. We can check the recording_type to find the type of recording. We are interested in the audio_transcript as recording_type.

Modify main.py to add the following function:

1#...

2# Get audio transcript for a given meeting

3defget_audio_transcript(self, meeting_id):

4 meeting_details = self.get_meeting_details(meeting_id)

5

6 aud_ts_uri = [i['download_url'] for i in meeting_details['recording_files'] if i['recording_type']=='audio_transcript'][0]

7 headers = self.get_authorization_header()

8

9 response = self._make_request(aud_ts_uri, headers=headers)

10# response.content contains audio transcript in bytes, so we need to decode it to understand the content.

11 decoded_content = response.content.decode("utf-8")

12 final_formatted_content = decoded_content.strip().split('\r\n\r') # format content

13

14# Print the audio transcript

15for line in final_formatted_content: print(line)

16#...

... See all 16 lines

Let's run the following to fetch the transcripts:

1$ python3

2>>> CLIENT_ID=''# Put your Client ID

3>>> CLIENT_SECRET=''# Put your CLIENT_SECRET

4>>> ACCOUNT_ID=''# Put your ACCOUNT_ID

5>>> from main import MyZoomSDKClient

6>>> client = MyZoomSDKClient(CLIENT_ID, CLIENT_SECRET, ACCOUNT_ID)

7>>> meetings = client.list_my_meetings()

8>>> client.get_audio_transcript(meetings[0][0])

This is an example output. Your output should be in a similar format:

1...

2WEBVTT

3

41

500:00:16.239 --> 00:00:27.079

6John: Hi, this is a testfor audio transcripts.

7

82

900:00:28.079 --> 00:00:30.239

10Wewake: I am going to say.

11

123

1300:00:30.869 --> 00:00:32.329

14Wewake: a few words.

15

164

1700:00:32.629 --> 00:00:41.649

18Wewake: I expect this to be recorded and available to me later.

19

205

2100:00:44.779 --> 00:00:46.509

22Wewake: That is it.

23

246

2500:00:52.219 --> 00:00:54.909

26Wewake: So simple.

27

287

2900:00:56.319 --> 00:01:00.269

30Wewake: We are done.

31

328

3300:01:00.749 --> 00:01:01.629

34Wewake: Bye.

... See all 34 lines

Bonus: Closed Caption

We can also retrieve the closed captions from the recording_files. For this, we would need to enable closed caption during the meeting. Here is the code to fetch it:

1#...

2# Get closed captions

3defget_closed_captions(self, meeting_id):

4 meeting_details = self.get_meeting_details(meeting_id)

5

6 cc_uri = [i['download_url'] for i in meeting_details['recording_files'] if i['recording_type']=='closed_caption'][0]

7 headers = self.get_authorization_header()

8

9 response = self._make_request(cc_uri, headers=headers)

10

11# response.content contains closed caption in bytes, so we need to decode it to understand the content.

12 decoded_content = response.content.decode("utf-8")

13 final_formatted_content = decoded_content.strip().split('\r\n\r') # format content

14

15# Print the closed captions

16for line in final_formatted_content: print(line)

17#...

... See all 17 lines

Run it:

1$ python3

2>>> CLIENT_ID=''# Put your Client ID

3>>> CLIENT_SECRET=''# Put your CLIENT_SECRET

4>>> ACCOUNT_ID=''# Put your ACCOUNT_ID

5>>> from main import MyZoomSDKClient

6>>> client = MyZoomSDKClient(CLIENT_ID, CLIENT_SECRET, ACCOUNT_ID)

7>>> meetings = client.list_my_meetings()

8>>> client.get_closed_captions(meetings[0][0])

Complete Code for the Zoom Client

1"""

2MyZoomSDKClient

3

4Simple Zoom SDK to get access_token, recordings, transcripts, and closed captions.

5for a Zoom meeting (with cloud recording). Requires client_id, client_secret and account_id

6"""

7import requests

8

9

10classMyZoomSDKClient:

11

12# Initialize the client with account_id, client_id, and client_secret

13def__init__(self, client_id, client_secret, account_id):

14 self.client_id = client_id

15 self.client_secret = client_secret

16 self.account_id = account_id

17 self.access_token = None

18 self.meetings = {}

19

20# Generate a new access token only if one does not exist, or if the user explicitly asks to generate

21# (using 'force=True' means generating a new token)

22defget_access_token(self, force=False):

23if self.access_token andnot force:

24return self.access_token

25

26 access_token_uri = "https://zoom.us/oauth/token"

27 data = {

28"grant_type": "account_credentials",

29"account_id": self.account_id,

30"client_id": self.client_id,

31"client_secret": self.client_secret

32 }

33 response = self._make_request(access_token_uri, data=data, method='POST')

34return response.json()["access_token"]

35

36# Generate authorization header using access_token

37defget_authorization_header(self):

38return { "Authorization": f"Bearer {self.get_access_token()}" }

39

40# List id and topic of all my meetings

41deflist_my_meetings(self):

42 list_meetings_uri = "https://api.zoom.us/v2/users/me/recordings"

43 headers = self.get_authorization_header()

44

45 response = self._make_request(list_meetings_uri, headers=headers)

46return [(x['id'], x['topic']) for x in response.json()['meetings']]

47

48# Get meeting details by ID

49defget_meeting_details(self, meeting_id):

50if meeting_id in self.meetings:

51return self.meetings[meeting_id]

52

53 meeting_details_url = f"https://api.zoom.us/v2/meetings/{meeting\_id}/recordings"

54 headers = self.get_authorization_header()

55

56 self.meetings[meeting_id] = self._make_request(meeting_details_url, headers=headers).json()

57return self.meetings[meeting_id]

58

59# Get audio transcript for a given meeting

60defget_audio_transcript(self, meeting_id):

61 meeting_details = self.get_meeting_details(meeting_id)

62

63 aud_ts_uri = [i['download_url'] for i in meeting_details['recording_files'] if i['recording_type']=='audio_transcript'][0]

64 headers = self.get_authorization_header()

65

66 response = self._make_request(aud_ts_uri, headers=headers)

67# response.content contains audio transcript in bytes, so we need to decode it to understand the content.

68 decoded_content = response.content.decode("utf-8")

69 final_formatted_content = decoded_content.strip().split('\r\n\r') # format content

70

71# Print the audio transcript

72for line in final_formatted_content: print(line)

73

74

75# Get closed captions

76defget_closed_captions(self, meeting_id):

77 meeting_details = self.get_meeting_details(meeting_id)

78

79 cc_uri = [i['download_url'] for i in meeting_details['recording_files'] if i['recording_type']=='closed_caption'][0]

80 headers = self.get_authorization_header()

81

82 response = self._make_request(cc_uri, headers=headers)

83

84# response.content contains closed caption in bytes, so we need to decode it to understand the content.

85 decoded_content = response.content.decode("utf-8")

86 final_formatted_content = decoded_content.strip().split('\r\n\r') # format content

87

88# Print the closed captions

89for line in final_formatted_content: print(line)

90

91def_make_request(self, uri, headers=None, method='GET', data=None):

92try:

93if method == 'POST':

94 response = requests.post(uri, headers=headers, data=data)

95else:

96 response = requests.get(uri, headers=headers)

97

98if response.status_code // 100 != 2:

99raise Exception('Invalid response from Zoom API. Please try again later.')

100return response

101except Exception as e:

102raise Exception('Invalid response from Zoom API. Please try again later. Error Message: ' + str(e))

... See all 102 lines

Limitations of the Zoom Cloud Recording API

You might have noticed how we made some specific choices when we created the Zoom App to get transcription. This is because the native Zoom APIs have several limitations:

1. You need to be on a Paid Plan

The Zoom account hosting the meeting must be on the Pro, Business, or Enterprise tier. The free Basic plan will not work.

2. You need to enable Zoom Cloud Recording

Transcripts are only produced if the user records their meeting using Zoom Cloud Recording (not Zoom local recording). Zoom also has live captions that appear without recording the meeting, but it does not produce a transcript file after the call unless the meeting is being recorded.

3. Only the Meeting Host can access the transcript

The recorded meeting is only stored in the host's account, so other users cannot access the meeting and transcript details.

4. Meeting Host must enable recording settings for the transcript to be generated

The audio transcript feature in Zoom is disabled by default. You must enable this setting in Zoom for transcription to be produced.

5. Not accessible without elevated plan

Users must be on a paid plan to access recording/transcribing with Zoom natively.

6. Transcripts can take a long time to become available

After the meeting has ended, it typically takes about 2 times the duration of the recorded meeting for all the recordings to be available. For example, the transcript of a 30 minute long meeting will be available 1 hour after the meeting is done. Depending on the load on Zoom's servers, processing time can take up to 24 hours.

7. Transcripts are not available in real-time

Zoom Cloud transcripts are only available after the meeting is done, so you won’t be able to get the transcription in real-time.

Workarounds

To workaround the above limitations, there are a few options:

Workaround 1: Use the Zoom RTMP Live-Streaming API

Zoom allows Live Streaming the meeting to custom apps, using the Real-Time Messaging Protocol (RTMP) protocol. This allows you to use a custom app to fetch the audio of the meeting. This audio can then be piped to any 3rd-party transcription service to get real-time transcripts.

Advantages:

  • You get real-time transcripts.
  • You can get transcripts in any language.

Disadvantages:

  • The setup is more complex. You need to set up a live-streaming server.
  • You also need to integrate with a 3rd-party service for transcription, which can add to the cost and complexity.
  • This also requires a Zoom paid plan.
  • This also requires you to be the host.

Workaround 2: Build a Zoom Meeting Bot

Zoom allows meeting bots to access the video and audio contents of the meetings.

Advantages:

  • You can get real-time transcripts.
  • You don't need a paid Zoom plan.
  • You don't need to be the host to access transcriptions.

Disadvantages:

  • Developing a meeting bot is quite complex since Zoom does not provide an API to call to build one.
  • There is a scale problem. Meeting bots require a separate instance of a Zoom client for each meeting. As the amount of meetings grows, this can become extremely difficult to manage. Also, it may blow up the infrastructure costs. It typically takes 6-12 months to build a stable meeting bot in its most basic form.
  • You need to build separate integrations for each platform that you want to support. Your Zoom integration will look different from your Google Meet integration which will differ from your Microsoft Teams integration. They each come with their own set of edge cases and required maintanence.

Recommended alternatives

  1. Recall.ai's Zoom Meeting Bot API, allows you to access transcripts, recordings, meeting metadata, and more across all major platforms. This means that you do not need to build or maintain integrations with each platform nor do your customers have to have elevated plans on each platform. Recall.ai handles all of the scaling, adapts to changes that the meeting platforms make, and deals with every edge case. The user just needs to add a few lines of code to launch a bot and then either retrieve the data after the call is over or specifying real-time data. We've got tutorials on how to get transcripts from Zoom and how to get recordings from Zoom using Recall.ai or you can get started with our Zoom Meeting Bot API today. Our API allows users to add the same functionality to Google Meet, Microsoft Teams, and more simply by changing the meeting url that is passed to the create bot endpoint.

  2. If the bot form factor doesn't work for your use case, you might benefit from a Desktop Recording SDK. A deskop SDK allows you to gather conversation data in your app. It should be noted that with a desktop SDK you will need to figure out your own consent flow. With Recall.ai's Desktop Recording SDK you get real-time and post-call data just as a meeting bot would provide.

Conclusion

We looked at how to programmatically access Zoom transcripts using the Zoom API, several limitations of the Zoom API, and workarounds you can use to overcome those limitations. If you need a Zoom transcript API and Zoom recording API rolled into one, Recall.ai is the answer.

References

Written By:

Vivek Sahu

Table of Contents

The API to get transcripts, recordings, and metadata from meetings.

Start for free Get a demo

Need help? Email us at support@recall.ai

Get transcripts, recordings and metadata from meetings

Start for free

Product

Meeting Bot API\ \ \ example Desktop Recording SDK\ \ \ example Mobile Recording SDK\ \ \ example Calendar Integration\ \ \ example Storage and Playback\ \ \ example

Company

Careers\ \ \ We're hiring! Blog\ \ \ example Case Studies\ \ \ example

Security

Security Portal\ \ \ example SOC 2\ \ \ example ISO 27001\ \ \ example HIPAA\ \ \ example GDPR\ \ \ example CCPA\ \ \ example

Legal

Privacy\ \ \ We're hiring! Terms of Use\ \ \ We're hiring!

Resources

API Docs\ \ \ example Pricing\ \ \ example Notetaker API\ \ \ example Meeting Recording API\ \ \ example Transcription API\ \ \ example Meeting Transcription API\ \ \ example Compliance Recording API\ \ \ example Speaker Diarization API\ \ \ example Slack Huddles API\ \ \ example

Compare

Recall.ai vs Attendee\ \ \ example Recall.ai vs Meeting BaaS\ \ \ example Recall.ai vs Nylas Notetaker\ \ \ example Recall.ai vs Skribby\ \ \ example

More

Meeting Bots

Google Meet Bot API\ \ \ example Microsoft Teams Bot API\ \ \ example Zoom Meeting Bot API\ \ \ example

Recording

Google Meet Recording API\ \ \ example Microsoft Teams Recording API\ \ \ example Zoom Meeting Recording API\ \ \ example

Transcription

Google Meet Transcription API\ \ \ example Microsoft Teams Transcription API\ \ \ example Zoom Meeting Transcription API\ \ \ example