Proctored assessments & technical interviews

Watch how the answer was actually written

A risk score tells you to be suspicious and hands you nothing to check. ProctorHire replays the whole sitting — every change to the answer, every paste, every tab switch — so you can see what happened, and what it examined and cleared.

Get started free

No credit card. Build a paper, send it to one candidate, and watch the replay.

Session playback — Backend Engineer screenExample
Which question was open3 questions · 1,352 changes
Q1 Sliding-window rate limiter
Q2 Refunds by customer
Q3 Idempotent webhook consumer
34:29 / 41:37Change 1,121 of 1,352
Skip dead time0.5x1x2x4x8x
Q3Idempotent webhook consumerpython
7 self.window = 60
8
9 def _key(self, tenant, route):
10 return f"rl:{tenant}:{route}"
11
12 def _prune(self, key, now):
13 cut = now - self.window
14 pipe = self.redis.pipeline()
15 pipe.zremrangebyscore(key, 0, cut)
16 pipe.zcard(key)
17 return pipe
18
19 def handle(self, tenant, event):
20 prior = self.store.get(event["id"])
592 characters34:29
272 characters arrived in one changeNo finding was made

Cleared by the cross-question provenance guard: these two helpers were already in this candidate’s own answer to question 1, matched character for character.

EvidenceIntegrity 40
Switched away from the test tabViolation
Pasted 30 characters into the editorViolation
Left fullscreenViolation
272 characters arrived in one changeCleared
165 characters arrived in one changeInsertion finding
The session playback screen, running on an example sitting. Every control drawn here is in the product; the candidate is not real, because no customer’s assessment belongs on a marketing page.

The problem

Right now you are guessing, in both directions

Two things happen in every technical hire that nobody can currently see, and a number between 0 and 100 settles neither of them.

The score does not show its working

An opaque risk figure tells you to be suspicious. It cannot tell you what to look at, you cannot act on it on your own, and you certainly cannot repeat it to the candidate when they ask why.

So honest candidates get rejected

Reformatting a file, undoing and redoing, reusing a helper you wrote twenty minutes ago on the previous question, pasting a column name off the schema the question handed you — to a detector that only counts, all of it looks like the real thing.

And a finished submission hides everything

By the time you read the answer there is nothing left to see. How it was written exists only while it is being written, and only if something was recording.

The proof

The evidence is the keystrokes

While a candidate sits an assessment, ProctorHire records the edit stream: every change, in order, per question. Playback merges it into one timeline and lays the integrity record on top of it.

Replay the whole sitting

Which question was open, when they moved between them, and how much was typed in each. The timeline is indexed by change rather than by clock, so a sitting with thirteen hundred separate changes in it is actually navigable — from half speed up to eight times, with a switch that skips the stretches where nobody typed.

Every event sits on the keystroke it happened at

A tab switch, a paste, a block that arrived all at once: one marker each, on the same axis as the typing. Open one and you get the answer exactly as it stood at that moment, and the clip recorded around it — eight seconds by default, and you set that. When there is no clip — the recording never reached storage, or the test was set up without screen recording at all — it says which of those happened instead of handing you a blank frame to draw your own conclusion from.

A marker is only placed where the data supports one

An event with no keystroke to sit on — a tab switch during a multiple-choice section, where there is no editor at all — is listed separately rather than pinned to the nearest one. Where a position had to be inferred, the marker is drawn hollow and the panel says how far off it might be.

Nothing is scored in secret

The integrity figure starts at 100 and subtracts the weights you set: 25 for a tab switch if you chose 25. The arithmetic is on the screen, so a hiring meeting can say “forty, because of two critical events and a fullscreen exit” out loud, and anybody in the room can check it.

Violation review — Backend Engineer screenExample
Violation reelsEvery occurrence of one type joined into a single video you can scrub, instead of one player each.
Left fullscreen ×2Build reelWindow unfocused ×9Building…
One sitting · 47:12Six tab switches, scattered through the recording
One reel · 0:48all 6 tab switches, cut together in order — and nothing else

0:16 of 0:48 — each block is one occurrence; click a block, or its marker above, to jump straight to it.

Occurrence 3 of 6 · Tab switchcritical+11:47 into the sitting

The test tab lost focus for 1:03. Its piece of the reel starts at 0:16 and runs 6.9s — the switch itself, with the seconds either side of it.

Every occurrence keeps the time it happened, so a reviewer who wants the rest of that moment can jump straight back to +11:47 in the full recording.

A violation reel, on an example sitting: six tab switches spread over 47 minutes, cut into one 48-second clip that is still labelled with when each moment happened. The six pieces are not the same length because they are not meant to be — an 8-second clip setting delivers 6 to 9 seconds, since the recorder can only cut on its own 3-second boundaries. The video itself is the one thing deliberately not drawn: it is a recording of a person, and no customer’s candidate belongs on a marketing page.

The difference

The part that clears people

A large block of text arriving in a single change is the strongest signal in the whole product. It is also exactly what happens when somebody reformats a file, cuts a function and pastes it back two lines down, moves their own working code from question 1 into question 3, or copies a table name off the schema the question put on their screen.

So before anything is reported, five guards try to explain the insertion. Each guard can only ever remove a finding, never add one. When one of them accounts for the text, the moment still appears on the timeline — marked Cleared, with the guard named and the reason written out. A reviewer watches the exact keystroke the block appeared at and reads why it is not a finding.

The five questions asked before anything is reported

  1. It is a rewrite of what was already therereformatting, an undo, a redo
  2. They had cut that text moments earliera cut and paste back into the same answer
  3. It is already somewhere else in the same answera duplicated block
  4. It is their own work, from another questioncode moved from question 1 into question 3
  5. The exam itself put it on their screena starter template, a prompt, a SQL schema

Cleared is a record, not a deletion

A detector that silently drops what it decided to ignore is unauditable. Every clearance stays on the timeline with the sentence that explains it, so the record shows what was examined, not only what survived. It is the difference between telling a candidate “the system did not flag you” and showing them the keystroke, the block, and the reason.

Answer similarity works the same way

Two submissions are compared as normalised token streams rather than as text, so renaming the variables, reindenting and deleting the comments does not defeat it. But the question’s own template, and the phrasing that every correct answer to that question shares, are struck out before the comparison runs. “They both used SELECT … GROUP BY” is never a match, because it is what a right answer looks like.

A finding you can dismiss is worth something. A dismissal you can show the candidate is worth considerably more.

Session playback — Platform Engineer screenExample
404 characters arrived in one changeEditor flagged a pasteQ3 · change 808 of 1,148 · 31:05

The answer went from 250 to 654 characters between two consecutive changes. 62% of what was on the screen landed at once, and nothing was replaced.

404Novel characters0Characters replaced31Largest earlier edit on Q3immediatelyTyping resumed
Insertion analysisEach guard can only remove a finding, never add one
  1. Was this a rewrite, a reformat or an undo?Similarity guardNo. Nothing was replaced: 404 characters in, none out.
  2. Had the candidate cut this same text from this question earlier?Removal-history guardNo. Nothing matching it was ever removed from question 3.
  3. Was it already on screen, further up the same answer?In-document guardNo. Question 3 held no copy of it.
  4. Was it already in this candidate's own editor on another question?Cross-question provenance guardYes. All 404 characters, verbatim, in question 2 — typed there 13:53 earlier.
  5. Did the question itself put this text on their screen?Question-material guardNot reached. Guard 4 already accounted for the text.
Q2Redis-backed rate limiterpython17:12
8 self.prefix = "rl"
9
10 def _key(self, tenant, route):
11 return f"{self.prefix}:{tenant}:{route}"
12
13 def _claim(self, key, ttl):
14 token = uuid4().hex
15 ok = self.redis.set(key, token, nx=True, px=ttl)
16 return token if ok else None
17
18 def _release(self, key, token):
19 if self.redis.get(key) == token:
20 self.redis.delete(key)
21
22 def _ttl(self, s):
23 return int(s * 1000)
Where the text was first typedchange 447
Q3Idempotency-key middlewarepython31:05
10 self.window = 60
11
12 def _key(self, tenant, route):
13 return f"{self.prefix}:{tenant}:{route}"
14
15 def _claim(self, key, ttl):
16 token = uuid4().hex
17 ok = self.redis.set(key, token, nx=True, px=ttl)
18 return token if ok else None
19
20 def _release(self, key, token):
21 if self.redis.get(key) == token:
22 self.redis.delete(key)
23
24 def _ttl(self, s):
25 return int(s * 1000)
Where it arrived, in one changechange 808

Both blocks are the same 404 characters — matched character for character, at line 10 of one answer and line 12 of the other.

No finding was madeCleared

Cleared by the cross-question provenance guard: the text was already in this candidate’s own editor elsewhere, matched character for character. This is a record of a large insertion that was examined and NOT reported.

Contributes 0 to the integrity scoreStays on the timeline where it happenedThe reason is on the record, for the reviewer and for the candidate
A clearance, on an example sitting. The insertion is real and the measurement is right — 404 characters in a single change, and the editor itself called it a paste — and it is still not a finding, because all 404 of those characters were already in this candidate’s own answer to question 2. The block is highlighted in both answers above and it is the same text in both, character for character. The candidate is invented; the guard order, the wording and the arithmetic are the product’s.

The queue

And then a person still decides

Playback is for the sitting you are unsure about. The rest of the time it is a list: submissions arriving against a paper, each carrying a score and an integrity figure, and none of them settled until you settle it.

EvaluationsFiltered to Backend Engineer — SQL & Python
AllNot submittedWaiting on youApprovedRejected
Not submitted yet
369
Waiting on you
239
Approved
65
Rejected
9
Six submissions against one test, each with a score, an integrity figure and an undecided verdict.
CandidateDecision
Priya Raghavan80 / 11090Clean1 violationPending
Daniel Okonjo78 / 11020High risk5 violationsPending
Mei-Ling Chen71 / 110100CleanNo violationsPending
Tomás Herrera64 / 11065Needs review2 violationsPending
Aarav Deshmukh59 / 11085Clean1 violationPending
Sofia Almeida43 / 11045High risk4 violationsPending

Integrity: how closely the attempt followed your proctoring rules. Every session starts at 100 and loses points for each thing the rules count, so higher is cleaner — 80 or above is Clean, 55 to 79 needs review, below 55 is high risk.

The review queue, redrawn: the test, the six candidates and every figure on them are invented. Score and integrity are two columns and not one blended number, and the top two rows are why — 80 out of 110 against an integrity of 90 with a single violation, and 78 out of 110 against a 20 with five. Two marks apart on the work, and nowhere near each other on how the work came to exist. Sort by integrity and they move to opposite ends of the table. A single “risk-adjusted score” would have returned one number for each of them and never said which half moved. Every row here reads Pending: nothing on this screen has been decided.

Two columns, because they are two questions

Whether the answer was any good, and how the answer came to exist, are not the same enquiry and do not combine into one figure. Anything that multiplies them has made your decision and hidden which half of it it was made on.

The figure arrives with its working

Under each integrity number is the count of events behind it — five violations, one, none. So the number is never the whole of what you are told, and “why is this one 20?” is answered on the row before anybody opens anything.

And when something else decides, it says so

Approve and reject here are a person’s: a submission waits until somebody presses one. A hiring workflow with a score rule in it can settle an assessment stage on its own — and the review it writes is stamped “auto-synced from the hiring workflow decision”, so a verdict nobody in the room remembers making still names the thing that made it.

The other leak

Two candidates, two different papers, the same test

The quickest way to break an assessment is for the person who sat it on Monday to send the questions to the person sitting it on Thursday. Each paper is drawn from pools, so there is no one paper to pass on — and the pools are balanced, so two people who were never asked the same question are still scored out of the same number.

Randomised delivery — Backend Engineer testExample

Every candidate sits 7 questions worth 38 marks, drawn from a bank of 21 worth 114.Every question a slot can draw is worth the same marks and sits in the same difficulty band, so the total is a property of the test and not of the draw. A test that breaks that cannot be published.

What each paper is drawn from3 pools · 21 questions
SQL, everydayDraws 2 of 6
Python, day to dayDraws 3 of 9
Designing a small serviceDraws 2 of 6
Two papers, as two candidates would sit them
Candidate 1preview:4Candidate 2preview:5
4 easy · 4 marks each · 16 on every paper
1Count orders per customer41Top five products by revenue4
2Find duplicate email addresses42Rows created in the last 7 days4
3Parse a CSV into records43Merge two dictionaries safely4
4Group a list of dicts by key44Flatten a nested list4
2 medium · 7 marks each · 14 on every paper
5Rate-limit an outbound client75Page through a cursor API7
6Choose a partition key76Cache a read-heavy list7
1 hard · 8 marks each · 8 on every paper
7Exactly-once from a queue87Backfill 400M rows without locking8
Paper total38 marks4 easy · 2 medium · 1 hardPaper total38 marks4 easy · 2 medium · 1 hard

These papers are comparable: identical length, identical marks, identical difficulty profile — so both scores are out of the same 38, and the candidate who sat it yesterday has nothing useful to pass on.

The test editor’s paper preview, redrawing an example test: the questions, the pools and both candidates are invented. And the limit, which the product states in its own code and not only here — equal marks and an equal difficulty mix narrow the difference between two papers; they do not make two questions an author both labelled “medium” equally hard.

The rest of it

And the whole hire runs in the same place

Playback is what makes the assessments worth trusting. These are the parts around it, so a candidate does not have to be copied between four tools and a spreadsheet on the way to an offer.

Assessments with proctoring built in

Coding, multiple-choice, SQL, Excel and written papers. While a candidate sits one, the session is monitored against rules you set, and what was recorded is shown to a reviewer alongside the answers rather than turned into a verdict.

Code that actually runs

Answers execute against test cases in 22 languages, with the console output the candidate saw.

Live technical interviews

Video and audio over WebRTC, with screen sharing, a Monaco editor both people can type in, and a whiteboard for the parts that are easier drawn.

One-way video screening

Recorded answers a candidate submits in their own time, so a first pass does not need two diaries to agree.

Structured scoring

Each round is run from a scorecard: the same questions, the same rating scales, a written reason and a clear recommendation - so two interviewers are judging the same thing.

The decisions that follow

Stages a candidate moves through, what happens automatically at each one, the funnel and scores behind it, and the offer letter at the end.

Hiring Analytics

Your pipeline at a glance, from application to hire. Every figure covers all time, not a date range, and refreshes each minute.

Candidates
391
In the pipeline
Avg test score
41%
315 attempts
Interviews
122
27 completed
Rejected
17
Closed out of the funnel
Hiring funnel

Every candidate you have ever added, by the stage they have reached. The right-hand % is conversion from the previous candidate stage.

Applied
391
Tested
147

Candidates who completed one of your tests. Testing is not a pipeline status, so this is not a step between Applied and Shortlisted and no conversion is shown for it.

Shortlisted
90
23%
Interview
70
78%
Hired
41
59%
The hiring analytics page, redrawn against an invented pipeline: every candidate ever added, by the stage they reached. The Tested row is the only one with no conversion percentage against it, because finishing a test is not a stage between Applied and Shortlisted, and a figure there would be inventing a step that does not exist. The product writes that on the row rather than quietly drawing the bar and letting you read a rate into it. The three percentages that are shown are computed from the counts beside them, here as in the product, so the figure cannot claim a conversion its own numbers contradict.

Straight answers

What it does not do

At least two of these will cost us a deal at some point. Publishing them is still cheaper than a buyer discovering them on their own in week six, and a page that admits its limits is the only kind whose other claims are worth reading.

No face detection, and no identity check from the webcam

The webcam records and the recording is shown to a reviewer. Nothing here decides that a face is missing, or that there are two of them. Those checks were taken out rather than shipped as a guess, because a guess about somebody’s face ends a career.

No SOC 2 report and no ISO 27001 certificate

Not pending, not in progress: absent. If your security review requires either one, we are not ready for you yet, and you should know that now rather than in week six.

It cannot see a second screen, or a phone in someone’s lap

No browser can. Where a moment looks like that, you get the two facts — when typing resumed, and how much was typed afterwards — clearly labelled as observations, scored at nothing and flagged as nothing.

No customer logos, and the people in the figures are invented

This is a new product with a small number of customers, and none of them has agreed to appear in anyone’s marketing. So the screens on this page are drawn rather than photographed: they are the real layouts, the real controls and the real wording, filled with data we made up. Nobody named in them exists and the counts — 391 in the pipeline, 41 hired — are invented, not customers and not our own usage either. They are there to show what the screens do, and they claim nothing about how many people use this. Everything above is checkable by using the product, which is the only proof we are entitled to offer yet.

Send one assessment and watch it back

Build a paper, publish it, and send it to a single candidate — yourself, if you like. Nothing has to be configured first, and you can see exactly what they will see before you send it. Then open the playback and decide whether the rest of this page was true.

Get started free

Name, email, company, password. No credit card, and nothing to install.