| name | client-view |
| description | Embeds Zoom Meeting SDK Web Client View through the ZoomMtg singleton: system check, WASM preload, init/join with passWord (capital W), and inMeetingServiceListener. Use for full-page Zoom meeting embeds or debugging blank-screen, black-overlay, and join-payload failures. Not for Zoom Component View custom tile layouts or Zoom Video SDK canvases. |
| version | 1.0.1 |
Zoom Meeting SDK Web — Client View
Client View renders a full-page Zoom meeting experience identical to the Zoom Web Client.
It uses the ZoomMtg global singleton with a callback-based API — minimal customization,
familiar Zoom UI, fast integration.
| Aspect | Details |
|---|
| API Object | ZoomMtg (global singleton) |
| API Style | Callback-based (success / error) |
| UI | Full-page takeover (occupies entire viewport) |
| Password param | passWord — capital W |
| Events | ZoomMtg.inMeetingServiceListener() |
| Best For | Quick integration, standard Zoom UI, minimal branding needs |
When to Use
- You need to embed a complete Zoom meeting in a web app with the standard Zoom interface.
- You want minimal customization — Client View gives you Zoom's own UI, not a custom layout.
- You are integrating via NPM or CDN and need the callback-based
ZoomMtg API.
- You are debugging blank screen, black overlay, join payload, or SPA z-index issues.
- You need to wire up event listeners (user join/leave, chat, recording, breakout rooms, etc.).
Do NOT use Client View if you need pixel-level control over the meeting UI layout — use
Component View instead (see Related Skills).
Prerequisites
- Zoom Meeting SDK credentials — SDK Key and SDK Secret (or Server-to-Server OAuth app
credentials) from the Zoom App Marketplace.
- Backend endpoint to generate the SDK JWT signature. Never expose SDK secrets in the
browser. Example placeholder:
YOUR_SDK_SECRET.
- HTTPS — required for media (WebRTC) and SharedArrayBuffer (gallery view).
- Supported browser — call
ZoomMtg.checkSystemRequirements() to verify.
- Node.js 18+ if using the NPM package.
- Windows host (PowerShell) is the primary development environment. All path examples use
Windows-style paths (e.g.
~\agent-skills\library\client-view\).
Reference Files
Load these reference files at the indicated points:
| File | When to Load |
|---|
references/index.md | At the start — lists all available reference docs and their purposes. |
../troubleshooting/error-codes.md | When debugging join failures, init errors, or unexpected SDK errors. |
../troubleshooting/common-issues.md | When encountering black screen, audio issues, or CORS errors. |
../concepts/sharedarraybuffer.md | When enabling gallery view or multi-speaker view (requires SharedArrayBuffer + COOP/COEP headers). |
RUNBOOK.md | Before deploying or debugging — 5-minute preflight and debugging checklist. |
Procedure
Step 1 — Install the SDK
NPM (recommended for bundlers):
npm install @zoom/meetingsdk --save
import { ZoomMtg } from '@zoom/meetingsdk';
CDN (script tags — replace {VERSION} with your target SDK version):
<script src="https://source.zoom.us/{VERSION}/lib/vendor/react.min.js"></script>
<script src="https://source.zoom.us/{VERSION}/lib/vendor/react-dom.min.js"></script>
<script src="https://source.zoom.us/{VERSION}/lib/vendor/redux.min.js"></script>
<script src="https://source.zoom.us/{VERSION}/lib/vendor/redux-thunk.min.js"></script>
<script src="https://source.zoom.us/{VERSION}/lib/vendor/lodash.min.js"></script>
<script src="https://source.zoom.us/zoom-meeting-{VERSION}.min.js"></script>
Step 2 — Complete Initialization Flow
This is the canonical 7-step flow. Follow it in order — skipping steps causes black screens
and join failures.
console.log('Requirements:', ZoomMtg.checkSystemRequirements());
ZoomMtg.preLoadWasm();
ZoomMtg.prepareWebSDK();
ZoomMtg.i18n.load('en-US');
ZoomMtg.i18n.onLoad(() => {
ZoomMtg.init({
leaveUrl: '/meeting-ended',
patchJsMedia: true,
disableCORP: !window.crossOriginIsolated,
success: () => {
console.log('SDK initialized');
const joinPayload = {
signature: signature,
meetingNumber: meetingNumber,
userName: userName,
passWord: passWord,
success: (res) => {
.();
.({});
.({
: .(, res..)
});
},
: .(, err)
};
(userEmail) joinPayload. = userEmail;
(tk) joinPayload. = tk;
(zak) joinPayload. = zak;
.(joinPayload);
},
: .(, err)
});
});
Step 3 — Configure ZoomMtg.init() Options
Required
| Parameter | Type | Description |
|---|
leaveUrl | string | URL to redirect to after leaving the meeting |
UI Customization
| Parameter | Type | Default | Description |
|---|
showMeetingHeader | boolean | true | Show meeting number and topic |
disableInvite | boolean | false | Hide invite button |
disableCallOut | boolean | false | Hide call out option |
disableRecord | boolean | false | Hide record button |
disableJoinAudio | boolean | false | Hide join audio option |
disablePreview | boolean | false | Skip audio/video preview |
audioPanelAlwaysOpen | boolean | false | Keep audio panel open |
showPureSharingContent | boolean | false | Prevent overlays on shared content |
videoHeader | boolean | true | Show video tile header |
isLockBottom | boolean | true | Show/hide footer |
videoDrag | boolean | true | Enable dragging video tiles |
sharingMode | string | 'both' | 'both' or 'fit' |
screenShare | |
Feature Toggles
| Parameter | Type | Default | Description |
|---|
isSupportAV | boolean | true | Enable audio/video |
isSupportChat | boolean | true | Enable in-meeting chat |
isSupportQA | boolean | true | Enable webinar Q&A |
isSupportCC | boolean | true | Enable closed captions |
isSupportPolling | boolean | true | Enable polling |
isSupportBreakout | boolean | true | Enable breakout rooms |
isSupportNonverbal | boolean | true | Enable nonverbal feedback |
isSupportSimulive | boolean | false | Enable Simulive |
disableVoIP | boolean | false | Disable VoIP |
disableReport | boolean | false | Disable report feature |
Video Quality
| Parameter | Type | Default | Description |
|---|
enableHD | boolean | true (≥2.8.0) | Enable 720p video |
enableFullHD | boolean | false | Enable 1080p for webinar attendees |
Advanced
| Parameter | Type | Default | Description |
|---|
debug | boolean | false | Enable debug logging |
patchJsMedia | boolean | false | Auto-apply media fixes |
disableCORP | boolean | false | Disable web isolation |
helper | string | '' | Path to helper.html |
externalLinkPage | string | — | Page for external links |
webEndpoint | string | — | For ZFG environments |
leaveOnPageUnload | boolean | false | Auto cleanup on page close |
isShowJoiningErrorDialog | boolean | true | Show error dialog on join failure |
meetingInfo | Array<string> | [...] | Meeting info fields to display |
inviteUrlFormat | string | '' | Custom invite URL format |
loginWindow | object | {width: 400, height: 380} | Login popup size |
Callbacks
| Parameter | Type | Description |
|---|
success | Function | Called on successful init |
error | Function | Called on init failure |
Step 4 — Configure ZoomMtg.join() Options
Required
| Parameter | Type | Description |
|---|
signature | string | SDK JWT from backend (v5.0+: must include appKey prefix) |
meetingNumber | string | number | Meeting or webinar number |
userName | string | Display name |
passWord | string | Meeting password (capital W) |
Authentication (conditional)
| Parameter | Type | When Required | Description |
|---|
zak | string | Starting as host | Host's Zoom Access Key |
tk | string | Registration required | Registrant token |
userEmail | string | Webinars | User email |
obfToken | string | March 2026+ | App Privilege Token |
Optional
| Parameter | Type | Description |
|---|
customerKey | string | Custom ID (max 36 chars) |
recordingToken | string | Local recording permission |
Callbacks
| Parameter | Type | Description |
|---|
success | Function | Called on successful join |
error | Function | Called on join failure |
Step 5 — Wire Event Listeners
Register listeners after ZoomMtg.init() success, before or inside join() success.
User Events
ZoomMtg.inMeetingServiceListener('onUserJoin', (data) => {
console.log('User joined:', data);
});
ZoomMtg.inMeetingServiceListener('onUserLeave', (data) => {
console.log('User left:', data);
});
ZoomMtg.inMeetingServiceListener('onUserUpdate', (data) => {
console.log('User updated:', data);
});
ZoomMtg.inMeetingServiceListener('onUserIsInWaitingRoom', (data) => {
console.log('User in waiting room:', data);
});
Meeting Status
ZoomMtg.inMeetingServiceListener('onMeetingStatus', (data) => {
console.log('Status:', data.status);
});
Audio/Video Events
ZoomMtg.inMeetingServiceListener('onActiveSpeaker', (data) => {
console.log('Active speaker:', data);
});
ZoomMtg.inMeetingServiceListener('onNetworkQualityChange', (data) => {
console.log('Network quality:', data);
});
ZoomMtg.inMeetingServiceListener('onAudioQos', (data) => {
console.log('Audio QoS:', data);
});
ZoomMtg.inMeetingServiceListener('onVideoQos', (data) => {
console.log('Video QoS:', data);
});
Chat & Communication
ZoomMtg.inMeetingServiceListener('onReceiveChatMsg', (data) => {
console.log('Chat message:', data);
});
ZoomMtg.inMeetingServiceListener('onReceiveTranscriptionMsg', (data) => {
console.log('Transcription:', data);
});
ZoomMtg.inMeetingServiceListener('onReceiveTranslateMsg', (data) => {
console.log('Translation:', data);
});
Recording & Sharing
ZoomMtg.inMeetingServiceListener('onRecordingChange', (data) => {
console.log('Recording status:', data);
});
ZoomMtg.inMeetingServiceListener('onShareContentChange', (data) => {
console.log('Share content:', data);
});
ZoomMtg.inMeetingServiceListener('receiveSharingChannelReady', (data) => {
console.log('Sharing channel ready:', data);
});
Breakout Rooms
ZoomMtg.inMeetingServiceListener('onRoomStatusChange', (data) => {
console.log('Breakout room status:', data);
});
Other Events
ZoomMtg.inMeetingServiceListener('onJoinSpeed', (data) => {
console.log('Join metrics:', data);
});
ZoomMtg.inMeetingServiceListener('onVbStatusChange', (data) => {
console.log('Virtual background status:', data);
});
ZoomMtg.inMeetingServiceListener('onFocusModeStatusChange', (data) => {
console.log('Focus mode:', data);
});
ZoomMtg.inMeetingServiceListener('onPictureInPicture', (data) => {
console.log('PiP status:', data);
});
ZoomMtg.inMeetingServiceListener('onClaimStatus', (data) => {
console.log('Host claim status:', data);
});
Step 6 — Use Common Methods (as needed)
Meeting Info
ZoomMtg.getCurrentUser({
success: (res) => console.log(res.result.currentUser)
});
ZoomMtg.getAttendeeslist({});
ZoomMtg.getCurrentMeetingInfo({
success: (res) => console.log(res)
});
ZoomMtg.getWebSDKVersion({
success: (version) => console.log(version)
});
Audio/Video Control
ZoomMtg.mute({ userId, mute: true });
ZoomMtg.muteAll({ muteAll: true });
ZoomMtg.stopIncomingAudio({ stop: true });
ZoomMtg.mirrorVideo({ mirror: true });
Chat
ZoomMtg.sendChat({
message: 'Hello!',
userId: 0
});
Meeting Control
ZoomMtg.leaveMeeting({});
ZoomMtg.endMeeting({});
ZoomMtg.lockMeeting({ lock: true });
Host Controls
ZoomMtg.makeHost({ userId });
ZoomMtg.makeCoHost({ userId });
ZoomMtg.withdrawCoHost({ userId });
ZoomMtg.expel({ userId });
ZoomMtg.putOnHold({ userId, bHold: true });
ZoomMtg.claimHostWithHostKey({ hostKey: '123456' });
ZoomMtg.reclaimHost({});
ZoomMtg.admitAll({});
Raise Hand
ZoomMtg.raiseHand({ userId });
ZoomMtg.lowerHand({ oderId });
ZoomMtg.lowerAllHands({});
Spotlight & Pin
ZoomMtg.operateSpotlight({ oderId, action: 'add' });
ZoomMtg.operatePin({ oderId, action: 'add' });
ZoomMtg.allowMultiPin({ allow: true });
Screen Share
ZoomMtg.startScreenShare({});
ZoomMtg.shareSource({ source });
Recording
ZoomMtg.record({ record: true });
ZoomMtg.showRecordFunction({ show: true });
Breakout Rooms
ZoomMtg.createBreakoutRoom({
rooms: [{ name: 'Room 1' }, { name: 'Room 2' }]
});
ZoomMtg.openBreakoutRooms({});
ZoomMtg.closeBreakoutRooms({});
ZoomMtg.joinBreakoutRoom({ roomId });
ZoomMtg.leaveBreakoutRoom({});
ZoomMtg.moveUserToBreakoutRoom({ oderId, roomId });
ZoomMtg.getBreakoutRoomStatus({
success: (res) => console.log(res)
});
Virtual Background
ZoomMtg.isSupportVirtualBackground({
success: (data) => console.log(data.result.isSupport)
});
ZoomMtg.setVirtualBackground({ imageUrl: '...' });
ZoomMtg.getVirtualBackgroundStatus({
success: (data) => console.log(data)
});
ZoomMtg.lockVirtualBackground({ lock: true });
UI Control
ZoomMtg.showMeetingHeader({ show: true });
ZoomMtg.showInviteFunction({ show: true });
ZoomMtg.showJoinAudioFunction({ show: true });
ZoomMtg.showCalloutFunction({ show: true });
ZoomMtg.reRender({ lang: 'de-DE' });
Language
ZoomMtg.i18n.load('de-DE');
ZoomMtg.i18n.reload('de-DE');
ZoomMtg.i18n.getCurrentLang();
ZoomMtg.i18n.getAll();
Pitfalls
HARD RULES (do not violate)
-
passWord — capital W. The join parameter is passWord, not password. Using the
wrong casing silently fails the join.
-
Never pass undefined for optional join fields. If userEmail, tk, zak, or other
optional fields are undefined, the SDK can throw Cannot read properties of undefined (reading 'toString') and the screen turns black. Only attach keys when they are non-empty
strings.
-
Never expose SDK credentials in the browser. The signature (SDK JWT) must be generated
on a backend. Use placeholder YOUR_SDK_SECRET in all example code — never commit real
secrets.
-
Do NOT manually create or remove #zmmtg-root or #aria-notify-area. The SDK creates
these DOM elements automatically. Manual manipulation breaks rendering.
-
Rate limits are enforced — do not exceed:
| Method | Limit |
|---|
join() | 10 seconds between calls |
callOut() | 10 seconds between calls |
mute() | 1 second between calls |
muteAll() | 5 seconds between calls |
-
defaultView: 'gallery' requires SharedArrayBuffer. Without COOP/COEP headers and
crossOriginIsolated === true, gallery view fails silently. Use defaultView: 'speaker'
unless you have fully configured SharedArrayBuffer. Load ../concepts/sharedarraybuffer.md
before attempting gallery or multi-speaker view.
-
disableCORP must reflect crossOriginIsolated status. Always set
disableCORP: !window.crossOriginIsolated — hardcoding false without cross-origin
isolation breaks media.
SPA (React/Next) Overlay Gotcha
If you call join() but see a blank or black area instead of the meeting UI, the Zoom
UI is likely rendering behind your app shell. Ensure #zmmtg-root occupies the viewport
and sits above all other fixed elements:
#zmmtg-root {
position: fixed !important;
inset: 0 !important;
z-index: 9999 !important;
}
Join Payload Sanitization Gotcha
If ZoomMtg.join() appears to succeed but the screen turns black and the console shows
Cannot read properties of undefined (reading 'toString'), you are passing undefined for
an optional field. Build the payload object with only required fields first, then
conditionally add optional fields:
const joinPayload = {
signature,
meetingNumber,
userName,
passWord,
success: (res) => { },
error: (err) => { }
};
if (userEmail) joinPayload.userEmail = userEmail;
if (tk) joinPayload.tk = tk;
if (zak) joinPayload.zak = zak;
ZoomMtg.join(joinPayload);
CDN Version Mismatch
All CDN script tags must use the same {VERSION}. Mixing versions of React, Redux, or
the Zoom SDK causes silent failures. Verify version consistency across all <script> tags.
i18n.load Must Complete Before init
ZoomMtg.init() must be called inside the i18n.onLoad() callback. Calling init()
before language resources finish loading causes rendering issues.
Verification
1. Check System Requirements
console.log('Requirements:', ZoomMtg.checkSystemRequirements());
Confirm the output lists your browser as supported.
2. Verify SDK Initialization
After ZoomMtg.init() success callback fires, check the console for SDK initialized.
If the error callback fires, load ../troubleshooting/error-codes.md and match the error code.
3. Verify Join Success
After ZoomMtg.join() success callback fires, check the console for Joined meeting.
Then verify post-join calls return data:
ZoomMtg.getCurrentUser({
success: (res) => {
console.log('Current user:', res.result.currentUser);
}
});
ZoomMtg.getAttendeeslist({});
4. Verify DOM Elements Exist
Open browser DevTools → Elements and confirm these elements exist (created by the SDK):
#zmmtg-root — main meeting container
#aria-notify-area — accessibility announcements
5. Verify Event Listeners Fire
ZoomMtg.inMeetingServiceListener('onMeetingStatus', (data) => {
console.log('Status:', data.status);
});
6. Verify SDK Version
ZoomMtg.getWebSDKVersion({
success: (version) => console.log('SDK version:', version)
});
Confirm the version matches your installed NPM package or CDN script version.
7. Run the Preflight Checklist
Load RUNBOOK.md and follow the 5-minute preflight checklist before deploying to production.
Related Skills
- Main Web SDK Skill —
../SKILL.md — overview of all Web SDK views and shared concepts.
- Component View —
../component-view/SKILL.md — for custom UI layouts with embedded
Zoom video tiles instead of full-page takeover.
- Reference Index —
references/index.md — complete list of reference docs.
- Error Codes —
../troubleshooting/error-codes.md — SDK error code lookup.
- Common Issues —
../troubleshooting/common-issues.md — black screen, audio, CORS fixes.
- SharedArrayBuffer Setup —
../concepts/sharedarraybuffer.md — COOP/COEP configuration
for gallery view.
- Official API Reference —
marketplacefront.zoom.us/sdk/meeting/web/index.html