Online Proctoring - React
Online proctoring lets proctors supervise candidates who take an exam from their own devices. The candidates and the proctors join one room for the exam. Each candidate publishes their camera, microphone and, when your exam requires it, their screen. The proctors watch and speak to candidates, and each candidate's session can be recorded for the exam record.
If you are new to VideoSDK, start with Concept and Architecture and Integrate React SDK, and check Supported Browsers for the devices your candidates use.
VideoSDK runs the live video, audio, screen share, recording and identity checks for the exam. Your application owns the exam content, any browser restrictions during the exam and any automated detection of suspicious behavior, and decides how to act on the signals described in this guide.
Set Up the Exam Session
Prepare the room and generate participant tokens on your backend before the exam begins.
- Keep the exam schedule and roster in your backend: VideoSDK does not keep the exam schedule or the list of registered candidates, so keep them in your exam platform. Create the room for the exam, issue the tokens when the exam is due, and move each candidate to the pre-exam screen when the exam is about to start.
- Create a room: Use the Create a Room API to create one room for the exam. Use the returned
roomIdto attach the exam to its schedule in your exam platform. - Validate the room: Before issuing candidate tokens, use the Validate a Room API to ensure the room is valid and available for the exam. If validation fails, do not issue the tokens, and report the failure to your exam platform.
- Configure participant permissions: Set
allow_joinandallow_modin each proctor's token so proctors can join directly, request access to a candidate's camera or microphone and mute candidates. Setask_joinin candidate tokens so each candidate waits in the lobby until a proctor admits them. IncluderoomIdandparticipantIdin every token payload, withversionset to2. See Authentication and Tokens. - Gate controls by role: Features such as recording, removing a participant and ending the meeting are available to all participants by default. Show these controls only in the proctor's console to keep exam actions under the proctors' control.
Configure the Candidate's Devices and Network
Candidates take exams from laptops and desktops, often over home networks, and need a setup that works without technical help. Prepare their devices and assess network quality before the exam, so a technical problem does not interrupt the exam itself.
Check Devices and Network Before the Exam
- Check permissions and devices: Provide a pre-exam screen where candidates can grant camera and microphone permissions, preview their camera, and test their microphone and speaker. Use
checkPermissions()andrequestPermission()from theuseMediaDevicehook to manage permissions. UsegetCameras()andgetMicrophones()to list available devices, andonDeviceChangedto refresh the list when a device is connected or disconnected. See Precall Setup. - Assess network quality: Use
runPreCallTest()to evaluate uplink and downlink quality on a scale from 1 (BAD) to 5 (EXCELLENT), along with the factors affecting each score. The uplink score matters most for a candidate who publishes a camera and a screen. Use the results to select an appropriate starting media configuration and inform the candidate about potential quality limitations. See Precall Setup. - Apply the verified setup: Pass the selected camera and microphone devices, their enabled states, and the chosen media configuration to
MeetingProviderso the meeting starts with the setup the candidate verified. The configuration can include a custom camera track created withcreateCameraVideoTrack(). See Precall Setup for recommended configurations based on the test results and Optimize Video Tracks. - Join after pre-exam checks: Set
joinWithoutUserInteractiontotrueonMeetingProviderif the candidate has already confirmed they are ready to join from the pre-exam screen. See Join Meeting.
Choose Which Streams Candidates Receive
By default, every participant receives the streams of everyone in the room, so candidates can see and hear one another. If your exam rules call for candidates to see only the proctors, choose which streams each candidate's application receives.
- Let candidates see each other: Keep the default behavior if your exam allows it. Each candidate's application receives the camera, microphone and screen share of every participant.
- Limit candidates to the proctors' streams: Set
autoConsumetofalseonMeetingProviderin the candidate's application. Then, for each proctor, callconsumeWebcamStreams()andconsumeMicStreams()from theuseParticipanthook. The candidate then sees and hears the proctors, while the streams of other candidates, including their screen shares, are not delivered to the device.
Switch Devices During the Exam
- Allow candidates to change devices: Provide in-exam controls to switch microphones or cameras if a device stops working or the candidate plugs in a headset. Use
getMics()andgetWebcams()from theuseMeetinghook to list available devices and theirdeviceIdandlabel. Pass the selecteddeviceIdtochangeMic()orchangeWebcam(). See Change Input Device.
Configure the Proctor's Console
The proctor supervises the exam from a console, verifying candidates before they start, watching their video and screens, and speaking to a candidate when needed. The console should provide controls for admitting candidates, monitoring them, communicating with them and controlling the exam.
Prepare the Proctor's Environment Before the Exam
- Check devices and network: Have each proctor complete the pre-call checks, including
runPreCallTest(), before admitting candidates. The downlink score matters most for a proctor who watches many video streams. See Precall Setup. - Apply a virtual background: Use the Virtual Background plugin to blur the proctor's background or replace it with an image, such as your organization's backdrop, so candidates see a professional view wherever the proctor works from. Apply the effect only to the proctor's camera so the candidates' video stays unaltered for the exam record. Virtual backgrounds are supported on desktop browsers.
- Suppress background noise: Use the Noise Suppression plugin on the proctor's microphone so candidates hear instructions clearly, even when the proctor works from a busy exam control room.
Admit Candidates from the Lobby
The waiting lobby only holds a candidate until a proctor admits them. Your system is responsible for the exam schedule and roster, as described in Set Up the Exam Session.
- Admit candidates: When candidates join with
ask_jointokens, they wait in the lobby until a proctor admits them. HandleonEntryRequestedin the proctor's console to receive each candidate'sparticipantIdandname, check them against the roster, then callallow()to admit them. Both the proctor and the candidate receiveonEntryRespondedwith the admissiondecision. See Waiting Lobby. - Handle a denied request: If the proctor denies the request, display an appropriate message to the candidate. Call
leave()in the candidate's application to disconnect them, since they remain connected until your application does so, then return them to the exam platform. See Leave or End Meeting.
Verify the Candidate's Identity and Environment
Confirm that the person at the screen is the registered candidate, and keep checking what the candidate's camera shows during the exam. Run the identity check after a proctor admits the candidate and before your application releases the exam. The identity steps below follow the flow described in Video KYC, with the proctor reviewing the images and the candidate providing them.
-
Capture the identity document and face: Ask the candidate to show their identity document and face to the camera. The candidate's application captures each image with
captureImage()and sends it to the proctor over PubSub in chunks, addressed only to that proctor so no other participant receives it. See Capture Identity Documents Remotely and Image Capturer. -
Verify the captured images: Send the images from your backend to the Identity Verification APIs:
- Face Match API compares the candidate's face with the photo you hold on file.
- Face Spoof Detection API checks the capture for signs of spoofing.
- OCR API reads the details on the identity document.
Your application decides whether a candidate passes, fails or needs a manual review by the proctor. See Verify the Captured Images.
-
Check the candidate's view during the exam: Have the candidate's application capture an image with
captureImage()at the interval your exam rules set, and send it to your backend or to the proctor. Use the Number of Face Detection API to detect when more than one face is in view, and feed the result into your own review rules. Setpersisttofalsewhen publishing the image chunks so the images are not kept in the session's message history. See Image Capturer.
Monitor the Candidates
- Watch the candidates in a grid: Show each candidate's video in a paginated grid, and let the proctor click a candidate to open their camera and screen in a larger view. Render each tile with the
VideoPlayercomponent, which requests a video quality that fits the tile size and pauses tiles that scroll out of view. See Layout and Grid Management, Scalability for Large Participants and Handle Large Rooms. - Watch the candidate's screen: If your exam needs screen sharing, the candidate's application starts it with
enableScreenShare()from theuseMeetinghook, and the proctor's console displays it usingscreenShareStream. Depending on your exam rules, sharing can begin as soon as the exam starts, or a proctor can request it mid-exam over PubSub. See Screen Share. - Show who is speaking: Use
onSpeakerChangedfrom theuseMeetinghook to highlight a candidate whose microphone picks up speech, so a proctor can spot talking during a silent exam. See Active Speaker Indication.
Communicate with Candidates
- Send a private message: To warn or instruct a single candidate, call
publish()with that candidate'sparticipantIdin thesendOnlyoption. The candidate can reply to the proctor the same way, and nobody else in the room sees the conversation. Setpersisttotrueto keep the messages in the session's message history, and download them as CSV from the VideoSDK session dashboard to add them to the exam record. See Private Chat. - Let candidates ask for help: Create a dedicated PubSub topic where a candidate can raise a hand, and show the incoming requests in the proctor's console in the order they arrive. See PubSub Overview.
- Give proctors microphone and camera controls: Provide microphone and camera controls in the proctor's console using
muteMic()andunmuteMic()andenableWebcam()anddisableWebcam()from theuseMeetinghook, so a proctor can mute themselves while observing and speak when a candidate needs help. See Mute / Unmute Mic and On / Off Camera.
Control the Exam
- Request access to the candidate's media: Use
enableWebcam()orenableMic()from theuseParticipanthook to request camera or microphone access when a candidate's device is off. HandleonWebcamRequestedoronMicRequestedin the candidate's application so the candidate can accept or decline the request. See Toggle Remote Participant Media. - Remove a candidate: Use
remove()from theuseParticipanthook to remove a candidate who ends their exam or breaks the exam rules, and record the reason in your own system. See Remove Participant. - End the exam: Call
end()from theuseMeetinghook when the exam is over to end the meeting for all participants. See Leave or End Meeting.
Configure the Exam Screen on Both Sides
These components are built into both the candidate's application and the proctor's console.
Show Participant Status
- Track participant joins and leaves: Use
onParticipantJoinedandonParticipantLeftfrom theuseMeetinghook to update each screen when a candidate or a proctor joins or disconnects. In the proctor's console, use it to keep the candidate list current and to note when a candidate leaves the exam. Theparticipantsmap provides the current list of participants in the meeting. See Participant Events. - Show microphone and camera status: Use
micOnandwebcamOnfrom theuseParticipanthook to indicate whether a participant's microphone and camera are enabled, such as on each candidate's tile in the proctor's console. See Display Audio and Video. - Monitor the incoming video stream: Use
onStreamStateChangedfrom theuseStreamhook to detect when a participant's video stream becomes active, stuck, or frozen, so each side can ask the other to check their connection before the exam continues. See Monitoring Remote Streams.
Keep the Session Reliable
These controls apply to both the candidate's application and the proctor's console.
Handle Network Changes During the Exam
Network conditions can change during an exam. Candidates may use home or mobile networks, while proctors may connect through an exam center or office network. VideoSDK adapts video quality to available bandwidth and provides network and media events that help your application respond to changing conditions.
- Keep both sides informed: Use the relevant quality events to notify candidates and proctors when network conditions affect video quality and when conditions improve. See Monitoring Network Quality for available events and Optimize for Low Bandwidth Networks for recommendations before and during the exam.
- Show the connection state: Use
onMeetingStateChangedfrom theuseMeetinghook to follow the meeting connection throughCONNECTING,CONNECTED,RECONNECTINGandDISCONNECTED. Show a reconnecting indicator on both screens while the state isRECONNECTING, so the candidate and the proctor know the exam is recovering rather than over, and return the candidate to the exam platform when it reachesDISCONNECTED. See Meeting Connection State Events. - Handle image transfer failures: Capturing an image locally is separate from transmitting the video stream, but sending the image to the proctor requires a working network connection. Show a pending state while the image is being transferred. Set a timeout and display an error if the transfer does not complete. Allow the proctor to retry the transfer or request a new capture, and confirm that the complete image has been received and validated before proceeding with the exam.
Handle Errors and Follow Best Practices
- Handle SDK errors: Use
onErrorfrom theuseMeetinghook to receive error information when a meeting operation fails. Display actionable feedback in the candidate's application and the proctor's console, and send relevant diagnostic details to your monitoring service so failures across exams stay visible to your team. Avoid including candidate data in logs. See Error Events. - Follow integration guidelines: Review the User Experience Guidelines and Developer Experience Guidelines to build a reliable, accessible exam experience.
Recording
Configure recording, storage delivery, and encryption based on what the exam record needs. Record each candidate separately, so a proctor reviewing one candidate's session opens one candidate's files, and a dispute about one candidate does not involve the others. The recording's delivery destination and encryption depend on your configured storage and encryption settings.
Choose the Recording Type
VideoSDK offers three types of recording. For an exam, the participant and track recordings give each candidate their own files. See Recording Overview.
- Participant recording: Records one participant's audio and video into a single file, such as one candidate's camera and microphone. Start it with the Start Participant Recording API. See Participant Recording (Individual).
- Participant track recording: Records a single track of one participant as its own file. Pass
kindasaudio,video,screen_audioorscreen_videoto record a candidate's camera, microphone or shared screen separately. Start it with the Start Track Recording API. See Participant Track Recording. - Meeting recording: Records the whole room, including every candidate's video, into one composed file. Use it only if your exam rules allow all candidates in a single recording. See Start and Stop.
Record Each Candidate
- Show a consent notice: Before candidates join, show each of them a notice that covers recording, screen sharing and image capture, and save their acceptance in your exam platform.
- Start the recording when the candidate joins: Your backend receives the
participant-joinedwebhook whenever anyone joins, proctors included, so match the participant against your roster to identify candidates. Then start that candidate's participant recording or track recording with the Start Participant Recording or Start Track Recording API. See Webhooks List. - Confirm each recording has started: Your backend receives the
participant-recording-startedwebhook when a recording begins, andparticipant-recording-failedif it fails. When recording is mandatory, keep the candidate on a waiting screen until their recording is confirmed, or have a proctor review the candidate before the exam continues. See Webhooks List. - Stop the recording and store the file: A candidate's recording ends when they leave or when the exam ends, and your backend receives the
participant-recording-stoppedwebhook. To end one earlier, call the Stop Participant Recording API or the Stop Track Recording API from your backend. To find files later, use the Fetch All Participant Recordings API or the Fetch All Track Recordings API, or fetch a single recording by its id. Attach each file to that candidate's exam record in your system. See Webhooks List.
Store Recordings in Your Own Storage
- Configure your own storage: Use Configure Recording Storage in the dashboard to deliver recordings to your own AWS S3, Azure Blob or GCP bucket. It is set per API key and includes a test step.
- Upload with a presigned URL: When stored credentials are not allowed, generate a presigned URL on your backend and pass it to the Start Recording API, so the recording is uploaded to one object for a limited time.
VideoSDK uploads recordings to your storage with the credentials you set up. If your storage only accepts uploads from approved IP addresses, you will need to approve VideoSDK's static IP addresses. Contact us to request them.
Encrypt and Decrypt Recordings
- Encrypt recordings at rest: Turn on Recording Encryption for the API key in the dashboard, under Cloud Storage Configuration, and provide an RSA public key. Each recording is encrypted with its own AES key before upload.
AES-256-GCMis recommended. - Decrypt with your private key: Each recording arrives as three files: the encrypted recording, the wrapped AES key and a metadata file. Decrypt them on your side with your private key. The guide includes a Node.js example.
Recording Encryption and transcription cannot be enabled together on one API key, since transcription runs on unencrypted recordings. Decide per API key which your exam record needs before configuring either.
Transcription
Live captions help candidates who are hard of hearing follow a proctor's spoken instructions, and candidates who work in a second language. Transcription is not available for an API key with Recording Encryption enabled.
Show Live Captions
- Display live captions: Use
startTranscription()from theuseTranscriptionhook to start real-time transcription. Each line is delivered throughonTranscriptionTextas speech is transcribed. CallstopTranscription()when captions are no longer needed. See Realtime Transcription.
Choose the Language
- Set the spoken language: Pass the appropriate language code to
startTranscription(). The default isen. See Supported Languages for available codes, including regional variants such asen-IN,hi, andes-419. - Translate captions when needed: If the proctors and candidates speak different languages, use Realtime Translation to help both sides follow the conversation.
Meet Compliance Requirements
Configure these session-wide controls to align your exams with your organization's data protection policies and regional requirements.
| Requirement | Control |
|---|---|
| Keep media within a region | Use Geo Fencing to restrict connections to VideoSDK servers in your specified regions, regardless of the candidate's location. See Geo Fencing. |
| Allow or restrict access by location | Use Geo IP Restriction to allow or deny access based on the candidate's IP address and your geographic rules, such as an exam open to one country. See Geo IP Restriction. |
| Encrypt media end to end | Use E2EE to encrypt media on the sender's device and decrypt it only on the receiver's device, preventing intermediaries, including VideoSDK servers, from accessing the media. Your application is responsible for generating and distributing encryption keys. See E2EE Setup. |
| Meet regulatory requirements | VideoSDK offers GDPR compliance with EU data residency and a Data Processing Agreement for candidates in the EU, and SOC 2 Type II, ISO 27001 and CERT-IN for institutional and certification body vendor reviews. GDPR compliance and the Data Processing Agreement are available as add-ons. |
If E2EE is enabled and you want to record the exam, use a custom recording template, which produces a meeting recording. See Customize Recording UI.
- Recording: Build the template with the React or JavaScript SDK and enable E2EE in it using the same key provider and shared key as your application, so the template can decrypt the media for recording. Deliver the key securely from your backend to the template over HTTPS rather than including it in the
templateUrl, then start the recording using the template'stemplateUrl. - Transcription: Realtime transcription is not available when E2EE is enabled.
Firewall and Debugging
Proctors often connect from an exam center or office network behind a firewall, and some candidates may use restricted networks as well. Configure firewall rules before the first exam to ensure the required VideoSDK services are reachable. If a session fails to connect, use the checks below to identify potential network restrictions.
Allow VideoSDK Traffic Through Your Firewall
-
Allow VideoSDK domains: The simplest approach is to allow all subdomains of
*.videosdk.liveover TCP and UDP on all ports. This covers the API, signaling, media, and TURN servers. See Firewall Setup. -
Allow specific hosts and ports: If your network policy requires explicit firewall rules, allow the following hosts and ports. VideoSDK can use the fallback transport when the primary connection is unavailable.
Server Host Primary Fallback API api.videosdk.liveTCP 443 — Signaling *.rm.videosdk.live, or the regional hosts listed in the Firewall Setup guideTCP 443 — Media media.videosdk.liveUDP 40000–60000 TCP 40000–60000 TURN turn.videosdk.liveUDP and TCP 3478 TCP 443 Also allow
sdk.videosdk.liveover TCP 443 if your console loads the SDK or the PubSub worker from the VideoSDK CDN. The full-access policy already covers it. -
Allow the PubSub worker in your Content Security Policy: PubSub runs in a web worker created from a
blob:URL. If the proctor's console runs under a strict Content Security Policy, allowblob:in theworker-srcdirective, or passpubsubWorkerUrltoMeetingProviderto load a pre-built worker from the VideoSDK CDN or your own domain. See CSP policy for PubSub. -
Use Cloud Proxy for restricted networks: If the required ports cannot be opened, use Cloud Proxy to route media through the proxy servers you specify. Choose UDP over TCP (the default), Force UDP, or Force TCP according to your network restrictions.
Debug Connection Issues
- Test the network before the first exam: Run
runPreCallTest()from the exam center's network after configuring the firewall. The test checks whether a call can transmit media in both directions. If it fails despite internet access, review the required hosts and ports above. See Precall Setup. - Check UDP connectivity: Set
preferredProtocoltoTCP_ONLYinMeetingProviderand try connecting again. If the call succeeds over TCP but fails with the defaultUDP_OVER_TCPconfiguration, investigate whether UDP traffic is blocked on the media or TURN ports. You can also configure Cloud Proxy for the affected network. - Inspect connection errors: Use
onErrorfrom theuseMeetinghook to capture the error code and message when a connection fails. Use this information to investigate whether the failure occurred during the API, signaling, or media stage, and forward relevant diagnostics to your monitoring service to identify affected networks. See Error Events. - Verify media flow: Use
getTransportStats()from theuseParticipanthook to inspect transport statistics and check whether traffic is flowing in both directions. If one direction shows no bitrate, investigate the corresponding network path and firewall rules. See Monitoring Transport Stats. - Collect connection logs: Call
setLogLevel()withConstants.LogLevel.DEBUGto collect detailed diagnostics while reproducing the issue. After troubleshooting, restore the log level toINFOorNONEas appropriate. See Log Level.
API Reference
The API references for all the methods and events utilized in this guide are provided below.
- runPreCallTest()
- setLogLevel()
- MeetingProvider
- joinWithoutUserInteraction
- createCameraVideoTrack()
- VideoPlayer
- checkPermissions()
- requestPermission()
- getCameras()
- getMicrophones()
- onDeviceChanged
- leave()
- end()
- muteMic()
- unmuteMic()
- enableWebcam()
- disableWebcam()
- enableScreenShare()
- getMics()
- changeMic()
- getWebcams()
- changeWebcam()
- participants
- consumeWebcamStreams()
- consumeMicStreams()
- enableMic()
- enableWebcam()
- remove()
- captureImage()
- getTransportStats()
- micOn
- webcamOn
- screenShareStream
- publish()
- onEntryRequested
- onEntryResponded
- onParticipantJoined
- onParticipantLeft
- onSpeakerChanged
- onMeetingStateChanged
- onError
- onWebcamRequested
- onMicRequested
- onStreamStateChanged
- startTranscription()
- stopTranscription()
- onTranscriptionText
- Create a Room
- Validate a Room
- Start Participant Recording
- Start Track Recording
- Start Recording
- Stop Participant Recording
- Stop Track Recording
- Fetch All Participant Recordings
- Fetch All Track Recordings
- Webhooks List
Got a Question? Ask us on discord

