Current participants in an active meeting

Developing what I thought would be a simple tool to retrieve the list of active participants in a Zoom meeting.

I’ve reviewed all the related topics I could find. It seems that many folks have tried and probably failed to achieve this goal. Instability, long delays, and complex rules about whether an email address is ever returned at all.
The list of issues is long and goes back quite a long way in the history of this API.

What has become really clear is that what should be a simple call produces results that are unusable.

  1. Records are probably out-of-date
  2. The meaning of join_time and leave_time across multiple records for the same user are either ambiguous or actually incorrect.
  3. The meaning of status (in_waiting_room | in_meeting) doesn’t match reality. Not even after resampling the query over several hours.
  4. The user_name varies depending upon an unknown set of criteria. Returning the account name, or the participant name within the meeting.

I’ve been working on analysing the results for several hours as the meeting participants moved in and out of breakout rooms. I left my own account logged in for the duration without moving into breakout rooms.

My own record in the output never changed from this:
in_waiting_room 2025-08-15T23:45:37Z 2025-08-15T23:46:30Z My Name

Here is the basic code sample I’m using so there is no ambiguity about which API being used and how it is being called.

ZOOM_PARTICIPANTS_URL = “https://api.zoom.us/v2/metrics/meetings/{}/participants”

def get_access_token(client_id, client_secret, account_id):
headers = {
“Authorization”: “Basic " + base64.b64encode(f”{client_id}:{client_secret}".encode()).decode()
}
data = {
“grant_type”: “account_credentials”,
“account_id”: account_id
}
response = requests.post(ZOOM_TOKEN_URL, headers=headers, data=data)
response.raise_for_status()
return response.json()[“access_token”]

def get_all_participants(meeting_id, access_token):
participants =
seen = set()
page_size = 150
next_page_token = None
headers = {
“Authorization”: f"Bearer {access_token}"
}

while True:
    params = {
        "type": "live",
        "page_size": page_size,
    }
    if next_page_token:
        params["next_page_token"] = next_page_token

    url = ZOOM_PARTICIPANTS_URL.format(meeting_id)
    response = requests.get(url, headers=headers, params=params)

    if response.status_code != 200:
        handle_http_error(response)

    data = response.json()

    for p in data.get("participants", []):
        # Create a unique key based on fields that identify a participant
        key = (p.get("participant_user_id"), p.get("email"), p.get("user_name"))
        if key not in seen:
            seen.add(key)
            participants.append(p)

    next_page_token = data.get("next_page_token")

    if not next_page_token:
        break

return participants

Hi @dsgreens, it sounds like this would be a good use case for participant events, particularly the meeting.participant_joined and the meeting.participant_joined_breakout_room events. You can also track the participant leave events similarly. Then you can save the list of participants as they move from room to room or joining/leaving the meeting

Alternatively, you could use a third party like Recall.ai to easily pull the list of participants in a meeting or receive real-time updates on participants!

what is the url in recall ai to easily pull the list of participants. I cant find there either

After you retrieve a bot from the Recall.ai api, the response will include an array of recordings. Inside each recording object, you’ll find a media_shortcuts.participant_events.data.participants_download_url property which you can use to get the list of participants, which will be returned as JSON in this schema.

Here’s the structure you should look for in the bot retrieval response:

{
  "recordings": [
    {
      "media_shortcuts": {
        "participant_events": {
          "data": {
            "participants_download_url": "download_url"
          }
        }
      }
    }
  ]
}

when i am calling get bot i am getting null as download url

    "recordings": [
        {
            "id": "5cf95196-395e-4904-8efb-ce6b5076e639",
            "created_at": "2025-09-23T08:19:17.003915Z",
            "started_at": "2025-09-23T08:19:17.003915Z",
            "completed_at": null,
            "expires_at": null,
            "status": {
                "code": "processing",
                "sub_code": null,
                "updated_at": "2025-09-23T08:19:17.003915Z"
            },
            "media_shortcuts": {
                "video_mixed": {
                    "id": "b8f5ac0e-6dca-4c99-be9c-c2e7b3f41b16",
                    "created_at": "2025-09-23T08:19:17.003915Z",
                    "status": {
                        "code": "processing",
                        "sub_code": null,
                        "updated_at": "2025-09-23T08:19:17.003915Z"
                    },
                    "metadata": {},
                    "data": {
                        "download_url": null
                    },
                    "format": "mp4"
                },
                "transcript": null,
                "participant_events": {
                    "id": "42b7c913-7217-496a-804f-b81a52147114",
                    "created_at": "2025-09-23T08:19:17.003915Z",
                    "status": {
                        "code": "processing",
                        "sub_code": null,
                        "updated_at": "2025-09-23T08:19:17.003915Z"
                    },
                    "metadata": {},
                    "data": {
                        "participant_events_download_url": null,
                        "speaker_timeline_download_url": null,
                        "participants_download_url": null
                    }
                },
                "meeting_metadata": {
                    "id": "e5a1f095-2114-4d97-b7f1-f051b1d8be05",
                    "created_at": "2025-09-23T08:19:17.003915Z",
                    "status": {
                        "code": "processing",
                        "sub_code": null,
                        "updated_at": "2025-09-23T08:19:17.003915Z"
                    },
                    "metadata": {},
                    "data": {
                        "title": "Test meeting",
                        "zoom": {
                            "meeting_uuid": "98F325E5-4011-44C4-905E-3256757ED798"
                        }
                    }
                },
                "audio_mixed": null
            },
            "metadata": {}
        }
    ],

after i was narrowing down, i see these links are only available after meeting ended/bot left the meeting so there is no way to get them live
in zoom api we can get them from metrics but here i dont see a way
could you pls point me to a resource where i can easily get them? am i missing something?

long story short, we need to send live messages within meeting chat private messages