proctoreye
v0.3.0
Published
ProctorEye browser SDK — webcam/screen capture, face detection, and violation reporting for embedding AI exam proctoring into your own site.
Maintainers
Keywords
Readme
proctoreye
Browser SDK for ProctorEye — webcam/screen capture and violation reporting, embedded directly in your own exam/assessment page.
Your backend opens a session with POST /v1/sessions/start, then calls POST /v1/candidates/start with your apiKey (server-to-server — never expose the API key to a browser) and gets back a candidateToken. Hand that token to this SDK on the page itself.
Install
npm install proctoreyeimport ProctorSDK from "proctoreye";
await ProctorSDK.start({
candidateToken, // from your backend's /v1/candidates/start call
apiBaseUrl: "https://your-proctoreye-instance.example.com",
captureConfig, // pass through whatever /v1/candidates/start returned
});
// later, when the exam/assessment ends:
ProctorSDK.stop();Named imports work too: import { start, stop } from "proctoreye".
More control than start()/stop()
start() covers "monitor everything automatically." These expose the same
pieces it uses internally, for anyone who wants more control.
isActive() — is monitoring currently running?
import { isActive } from "proctoreye";
if (isActive()) {
showRecordingBadge();
}reportEvent(type, meta?) — report an event from your own UI logic
Reports one of the three browser-witnessed event types through the same
candidate start() uses — useful if your own page has its own reason to
believe one of these happened, instead of only relying on the SDK's
automatic listeners. The server only accepts "tab_blur", "wrong_share_type",
or "share_revoked" — it can't be used to fake an AI-only violation type.
Throws if called before start().
import { reportEvent } from "proctoreye";
// e.g. your own custom UI detected the candidate navigated away
await reportEvent("tab_blur", { durationMs: 4200 });getWebcamStream() / getEntireScreenStream() — build your own permission UI
The same functions start() calls internally, exposed directly — for a
custom "allow camera" priming screen (e.g. show a live preview before the
candidate commits) instead of start()'s single all-at-once prompt.
getEntireScreenStream takes a callback that fires each time the candidate
picks a tab/window instead of the entire screen — it keeps re-prompting
until they pick "entire screen."
import { getWebcamStream, getEntireScreenStream } from "proctoreye";
const preview = document.querySelector("video");
const webcamStream = await getWebcamStream();
preview.srcObject = webcamStream; // show it before officially starting
const screenStream = await getEntireScreenStream(() => {
alert("Please share your entire screen, not just a tab or window.");
});No build step? Use the script tag instead
Same SDK, same API, zero install:
<script src="https://unpkg.com/proctoreye"></script>
<script>
await ProctorSDK.start({ candidateToken, apiBaseUrl, captureConfig });
</script>What it does
- Requests webcam and/or screen access based on
captureConfig(either can be off). - Rejects a tab/window screen-share and re-prompts until the entire screen is shared.
- Uploads a frame from each active stream on a timer (
captureConfig.aiIntervalSec). - Reports tab-switch and screen-share-revoked events immediately, not on the next tick.
stop()releases the camera/screen and stops all reporting — always call it when the monitored attempt ends.
See your ProctorEye dashboard's Settings page for the capture-interval and policy options captureConfig accepts.
