Build your own proctoring system only when proctoring is your product and you can fund a team to own it indefinitely. Buy it when proctoring is a feature of something else you sell. The camera preview is the part you can prototype in an afternoon. The real cost is everything behind it: a server-side scoring pipeline the candidate cannot tamper with, face analysis that turns frames into an identity verdict, capture that survives a refresh or a network drop, and a biometric-data compliance posture that never stops needing attention. This page breaks down what you are actually signing up to build, so the decision is made on the hard parts rather than the easy one.
Schedule a DemoOpening a webcam in the browser takes a few lines, and a demo that shows the candidate’s face in a corner looks like proctoring. It is not. A demo is not a system that has to produce a defensible verdict on an exam a candidate may contest. Judging the build on how quickly you can show a camera feed is how teams underestimate the work by an order of magnitude, because none of the expensive parts are visible in that first demo.
A useful way to frame the decision is the first question in this series: whether you need an LMS plugin, a browser SDK, or a REST API. Build-versus-buy is the same question one level up. If none of the integration surfaces fit, you are considering building the whole thing, and the parts below are what that means.
A working proctoring system is not one feature. It is a set of subsystems that each stand alone, and skipping any one of them produces evidence that does not hold up. Here is what the browser SDK and the API already do, reframed as the components a from-scratch build has to own.
| Subsystem | What it has to do | Why it is harder than it looks |
|---|---|---|
| Resilient capture | Survive refresh, tab close, and network drop without splitting one attempt into several reports. | Needs a stable attempt identity, an offline-tolerant event queue, and a flush on page unload. |
| Keyframe pipeline | Capture periodic stills, not continuous video, and move image bytes out of your API path. | Continuous video is expensive to store; routing frames through your API makes it your bottleneck. |
| Face analysis | Per-frame presence, absence, multiple faces, and identity match against a reference photo. | A machine-learning problem with its own models, thresholds, and a steady false-positive budget. |
| Audio analysis | Voice activity and speaker count without recording a continuous audio stream. | Another model to run and tune, with its own privacy footprint. |
| Anti-tamper scoring | Compute the integrity verdict server-side so the candidate cannot edit the outcome. | The browser is the part the candidate controls; any score computed there is worthless. |
| Liveness and heartbeat | Track a heartbeat so a client that goes silent is itself a signal, and a pre-flight system check. | Absence of data is evidence; you have to model it deliberately, not ignore gaps. |
None of these is a feature flag. Each is a project with its own models, its own failure modes, and its own tests. Capture alone has to handle a candidate who refreshes, loses connectivity, or closes a tab and comes back, all without fragmenting one attempt into several reports. For how much nuance sits in just that one subsystem, see handling the exam session lifecycle.
It helps to see the other side concretely. The entire browser-side integration when you buy it is one call to create a session and one to start it. Your backend mints the session with your API key, which never enters the browser, and reads the finished report afterward.
// The entire browser integration when you buy it.
import { ProctorLink } from '@proctorlink/sdk';
const session = ProctorLink.createSession({
jwt: sessionJwt, // session_jwt from POST /v1/sessions
sessionId, // session_id from the same response
});
// Safety net if the token outlives the exam: re-mint the SAME attempt_id
// (which resumes the same session) and hand the new token back.
session.on('token-expired', async () => {
const { session_jwt } = await mintSession({ attempt_id: attemptId });
session.updateToken(session_jwt);
});
await session.start(); // camera up, keyframes and events flowing
// when the attempt finishes:
session.stop();
session.destroy();The server-to-server side is two calls: mint, then fetch. The browser only ever holds a short-lived token scoped to one attempt, so there is nothing for a candidate to lift.
// Your backend mints a session. Your API key never enters the browser.
POST /v1/sessions
access-token: <YOUR_ACCESS_TOKEN>
secret-token: <YOUR_SECRET_TOKEN>
content-type: application/json
{
"external_user_id": "user-9f3c1a", // your opaque ID, not a name or email
"exam_id": "math-101-final",
"attempt_id": "attempt-789", // stable per attempt, enables resume
"allowed_origins": ["https://exams.yourcompany.com"]
}
// After the attempt, fetch the finished report from your backend.
GET /v1/sessions/6a7b18df70e4f8ecf2597b6fThat is the whole integration surface. Everything in the subsystem table above sits behind these calls, maintained by someone else. For the full version of this integration in a framework, see how to add proctoring to a web application.
Of everything on the build list, the scoring model is the one most teams get wrong, because the obvious place to compute it is the wrong one. If the score is calculated in the browser, the candidate controls the exact component that decides whether they passed. The verdict has to be computed server-side, from signals collected in a part of the page the candidate cannot reach, or the whole system is theatre.
A defensible score is also explainable. It is not a single opaque number: it is a value with an itemised, weighted breakdown that a human reviewer can read and defend if the outcome is challenged. Face analysis drives the verdict; browser events like a tab switch stay pooled and capped so ordinary behaviour cannot manufacture a flag. Getting that balance wrong in either direction, flagging innocent candidates or missing real impersonation, is how an in-house score loses the trust of the exam board that relies on it.
// The verdict you would otherwise have to build and defend yourself.
// Computed server-side, so the candidate cannot influence it.
{
"status": "validated",
"integrity": {
"score": 72,
"level": "medium",
"flagged": true,
"identity_match": "pass",
"reasons": [
{ "code": "no_face", "detail": "...", "weight": -18 },
{ "code": "browser_activity", "detail": "...", "weight": -10 }
]
}
}Designing a model like this, and defending the weighting, is a project in itself. The full treatment is in how to design an exam integrity score, and the reasoning behind automated versus human verdicts is in AI proctoring vs live proctoring.
Set side by side, the trade is clearer. Building gives you full control and a permanent maintenance bill. Buying trades some control for a surface you can integrate against in an afternoon and never have to patch when a browser changes.
| Concern | Build in-house | Buy (ProctorLink) |
|---|---|---|
| Browser integration | Camera, fullscreen, clipboard, focus, and device-change handling across every browser. | A thin loader (~3 KB) mounts a cross-origin iframe enclave. One start() call. |
| The verdict | Design, weight, and defend a scoring model, then keep it server-side and tamper-proof. | A server-side integrity score with itemised, weighted reasons you read from the report. |
| Identity matching | Train or license a face model, store reference photos, run per-frame comparison. | Reference photo at mint or via the SDK; identity_match returned in the report. |
| Camera permission UX | Re-prompt the candidate on every customer domain that embeds you. | Permission binds to the enclave origin, so it persists across every site using it. |
| Browser-change maintenance | Permanent. Each browser release can break detection silently. | Absorbed by the vendor. The SDK and enclave are versioned together. |
| Biometric-data compliance | Consent, retention, deletion, data minimisation, and sub-processor records, all yours. | Still your obligation, but the architecture is built to support it. |
The camera-permission row is a good example of value that is invisible until you hit it. ProctorLink mounts a cross-origin iframe enclave, and the camera permission binds to that enclave origin, so a candidate who has granted it once is not re-prompted on the next site that embeds it. Build it yourself and every customer domain prompts afresh. The reasoning is in why proctoring runs in a cross-origin iframe.
Some costs do not go away by building, because they are properties of the web platform, not gaps in any one product. A browser tab cannot see other applications, a second device, a virtual machine, or a remote-desktop session. That is why serious proctoring tiers into a browser SDK, a browser extension, and a desktop agent, and building in-house means building that tiering yourself if you need it.
The rest of the platform limits are the same for everyone. Multi-monitor detection is Chrome-only and permission-gated. Virtual cameras are detectable as a signal through device heuristics, never as proof. iOS Safari has no screen-capture API and suspends the camera when the tab is backgrounded. Face analysis is probabilistic, so the honest result is “frames where no face was detected”, not “the candidate left the room”. Building your own system does not lift any of these constraints. It just makes them your job to discover, document, and explain. For where the line actually falls, see what browser-based proctoring can and cannot detect.
The moment you capture a face, you are processing biometric data, and that obligation outlives any single release. Facial images and the face templates derived from them are biometric data under India’s DPDP Act, GDPR Article 9, and Illinois BIPA, the last of which carries statutory damages assessed per violation. Build the system yourself and you own all of it: explicit pre-capture consent, a chosen and documented retention period, honouring deletion requests, data minimisation, and a documented list of every sub-processor that touches a frame.
Buying does not remove this obligation, but a platform designed for it is built to support the parts you control: an opaque external_user_id so you are not handing over names or emails, periodic keyframes instead of continuous video, and frames that upload straight to object storage rather than through an API. The full breakdown of what each law asks is in proctoring and biometric data: DPDP, GDPR Article 9, and BIPA. If you serve Indian institutions specifically, see online exam proctoring in India. And if your route to market is Moodle, the best Moodle proctoring plugin comparison shows the buy option as a plugin rather than an SDK.
Build when proctoring is the product you sell, the differentiation is in the detection itself, and you can staff a team to own capture, models, browser compatibility, and compliance for as long as the product lives. Buy when proctoring is a feature that makes your real product more valuable, when time to market matters, and when you would rather integrate against a maintained surface than carry a permanent detection-and-compliance team.
Across published deployments, ProctorLink has supported more than one million proctored exam sessions (methodology note below). Full cohort sizes and outcomes are on the case studies page, and the whole developer series starts from the knowledge hub.
Institutions evaluating proctoring tools often look for independent feedback outside vendor case studies. ProctorLink is listed on G2, where Moodle administrators and training teams share verified product reviews.
Read ProctorLink reviews on G2 →Deployment statistics and product behaviour described in this guide link to the sources below.
Before you commit to a build, see exactly what the buy path gives you. Sign up at app.proctorlink.com to get your API keys, run a session, and read a full server-side report.
Create an account at app.proctorlink.com to get your SDK credentials and run a live session.
Install @proctorlink/sdk, the thin loader that mounts the enclave and captures keyframes.
Walk through the build-versus-buy trade for your product in a 30-minute call.
Per-session and subscription models for custom applications and LMS exams.
Which integration surface fits before you decide to build the whole thing.
The hardest subsystem on the build list, explained end to end.
The compliance obligation you inherit the moment you capture a face.
Back to the knowledge hub for the full SDK and proctoring series.
Online proctoring supervises remote exams via webcam and microphone inside your LMS, logging rule violations with timestamps so reviewers judge flagged cases, not every session.
AI proctoring uses machine learning to automatically detect suspicious exam behaviour such as multiple faces, tab switching, and absence from the camera.
A comparison of leading Moodle proctoring plugins for universities that need native LMS integration, AI monitoring, and institution-owned data.
How university exam offices choose online proctoring software for entrance grids, finals, and multi-faculty calendars, including stakeholder RFPs and centre-vs-online cost tradeoffs.
How certification bodies and training providers use online proctoring for identity proofing, item-bank protection, and defensible, audit-ready credentialing exams.
A side-by-side comparison of AI proctoring and live human proctoring for cost, scale, accuracy, and exam security.
Practical steps to reduce cheating in Moodle quizzes using proctoring settings, question banks, timing controls, and AI monitoring.
Feature-by-feature comparison of Moodle proctoring plugins covering integration, AI detection, pricing, and data storage.
A guide to online exam proctoring for Indian universities and certification providers, including compliance, pricing in INR, and local case studies.
How to choose between a proctoring LMS plugin, a browser SDK, and a REST API when adding proctoring to software you already own, with a decision guide and code examples.
A step-by-step guide to adding exam proctoring to a web app you own: mint a session on your backend, run the browser SDK, and read a server-side integrity report, with code from the API reference.
What browser-based proctoring can detect (tab switches, clipboard, faces, identity) and what it cannot (phones, a second monitor, a virtual machine), and why the tiering exists.
A step-by-step guide to adding exam proctoring to a React app: mint a session on your backend, wrap the browser SDK in a useEffect hook, handle StrictMode and token expiry, and read a server-side integrity report.
A step-by-step guide to adding exam proctoring to an Angular app: mint a session on your backend, hold the browser SDK in an injectable service, start it in ngOnInit and tear it down in ngOnDestroy, handle NgZone and token expiry, and read a server-side integrity report.
How LTI 1.3 connects a proctoring tool to your LMS: the OpenID Connect launch handshake, why it replaces LTI 1.1 shared secrets, how it compares to a Moodle plugin and the browser SDK, and how to read the same server-side integrity report.
A step-by-step guide to adding exam proctoring to an assessment platform you built: map your users, exams, and attempts to a session, mint it on your backend, run the browser SDK in your exam runner, and route the server-side integrity report into your own review workflow.
Why the ProctorLink SDK mounts a cross-origin iframe enclave instead of running in your page: the camera permission binds to the enclave origin and persists across sites, the session token stays out of host-page JavaScript, and the integrity score is computed server-side.
How a proctored exam survives a tab close, a refresh, and a network drop without fragmenting into several reports: resume by a stable attempt_id, an offline-tolerant event queue, token-expired handling, and tearing down an SPA route change without ending the attempt.
How to design a defensible exam integrity score: a server-side number from 0 to 100 with itemised, weighted penalties, where face analysis drives the verdict, browser events stay pooled and capped as reviewer context, and the score triages for human review rather than failing a candidate automatically.
Why facial images and face templates captured during proctoring are biometric data under India's DPDP Act, GDPR Article 9, and Illinois BIPA, what an institution must do about consent, retention, deletion, and sub-processors, and how the ProctorLink architecture is built to support those obligations.
One create-session call, one start, a server-side verdict you can defend. Run a real session and read the report before you commit a team to building it yourself.