Purpose
Retrieve and structurally extract a candidate's WAEC Ghana examination result from the official checker. Include candidate details, examination centre, card usage, subjects, grades, interpretations, disclaimers, visible errors, and screenshot/PDF artifacts when requested.
When to Use
Use when the caller provides the candidate/index number, examination type, examination year, voucher serial number, PIN, and confirmation candidate number required by the form.
Workflow
- Navigate directly to
https://ghana.waecdirect.org/and populate the legacy form in one browser batch:input#candid={candidate-number}select#examtype={exam-type-code}; WASSCE School is01select#examyear={exam-year}input#serial={serial-number}input#pin={pin}input#ccandid={candidate-number}select[name='cexamyear']orselect#select={exam-year}- Leave the date-of-birth controls blank for WASSCE School unless the site explicitly requires them.
- Submit
input[name='Submit']. For WASSCE School, wait for the jQuery UI dialog[role='dialog'], then activate the button whose trimmed visible text is exactlyAgree. The dialog's handler opens a named popupresultsand submits the form toresults.asp. If the dialog closes without submitting, submit the form once more after agreement. - Capture the newly opened same-site popup, excluding the opener. Prefer the page whose URL is
https://ghana.waecdirect.org/displayresults.asp; otherwise identify it by titleWAECDIRECT ONLINE INFORMATION SERVICE - RESULTSor body text containingCandidate's Details,Result Checking, orIndex Number. Wait for its result table before extracting. - Bring the result popup to the front. For screenshots or PDF generation, request the browser-level maximize/window-management operation; a page-side
window.moveTo(0,0); window.resizeTo(screen.availWidth,screen.availHeight)attempt is only a best effort. - Run this evaluator once in the loaded result-popup page context:
(() => {
const clean = (value) => (value || "").replace(/\\s+/g, " ").trim();
const rows = [...document.querySelectorAll("table tr")]
.map((tr) =>
[...tr.querySelectorAll(":scope > th, :scope > td")].map((cell) =>
clean(cell.innerText),
),
)
.filter((row) => row.some(Boolean));
const findValue = (label) => {
const row = rows.find(
(r) => r.length >= 2 && clean(r[0]).toLowerCase() === label.toLowerCase(),
);
return row ? clean(row.slice(1).join(" ")) : "";
};
const cardStart = rows.findIndex((r) =>
r.some((c) => c.toLowerCase() === "card details"),
);
const resultStart = rows.findIndex((r) =>
r.some((c) => c.toLowerCase() === "results"),
);
const cardEnd = resultStart > cardStart ? resultStart : rows.length;
const cardDetails =
cardStart >= 0
? rows
.slice(cardStart + 1, cardEnd)
.filter((r) => r.length >= 2)
.map((r) => ({ label: r[0], value: clean(r.slice(1).join(" ")) }))
: [];
const results =
resultStart >= 0
? rows
.slice(resultStart + 1)
.filter(
(r) =>
r.length >= 3 &&
r[0] &&
r[1] &&
r[2] &&
!r[0].toLowerCase().includes("click to print"),
)
.map((r) => ({
subject: r[0],
grade: r[1],
interpretation: clean(r.slice(2).join(" ")),
}))
: [];
const disclaimer = [...document.querySelectorAll(".disclaimer")]
.map((e) => clean(e.innerText))
.filter(Boolean);
const errorMessages = [
...document.querySelectorAll(
'.error, .errors, [class*="error"], [id*="error"], [role="alert"]',
),
]
.map((e) => clean(e.innerText))
.filter(Boolean);
return {
url: location.href,
title: document.title,
viewport: { width: innerWidth, height: innerHeight },
candidate: {
indexNumber: findValue("Index Number"),
candidateName: findValue("Candidate Name"),
examType: findValue("Type of Examination"),
examinationCentre: findValue("Examination Centre"),
},
cardDetails,
results,
disclaimer,
errorMessages,
text: clean(document.body.innerText),
tables: rows,
};
})();- If requested, capture a screenshot of the result popup after maximizing it. For PDF output, use the result page's
a[href='javascript:window.print()']link or browser print-to-PDF facility, and report the saved artifact or any print/PDF failure.
Site-Specific Gotchas
- The checker is a legacy POST form whose action is
/results.asp; the final result is normally returned at/displayresults.asp. Do not fabricate a direct result URL or omit the POST/session flow. - Form controls submit option values rather than labels. WASSCE School is exam-type value
01. - The candidate/index number must be entered in both
#candidand#ccandid, and the year must be entered in both examination-year selectors. - The agreement is a jQuery UI modal. Locate
Agreeby exact visible text rather than button position; the dialog may render only after a short delay. - Submission opens a small named popup
results; popup detection should exclude the opener and tolerate an initially blank URL before navigation to/displayresults.asp. - The result page uses nested legacy tables. Candidate metadata and card details occur before the
Resultsheading; subject rows contain subject, grade, and interpretation. Preserve values such asXandABSENT. - The result page clears the PIN and confirmation fields in the opener after loading. Never return the PIN or voucher serial in extracted output unless explicitly requested.
- The print link commonly invokes
javascript:window.print(). Browser print dialogs, popup creation, viewport maximization, and PDF support vary by environment. - The evaluator reads only the current result page and performs no network requests.
Expected Output
Return the evaluator object containing candidate metadata, cardDetails, results, disclaimers, visible errorMessages, complete visible text, table rows, URL/title/viewport metadata, and any screenshot or PDF artifact. Include concise status information for blocked popups, failed submission, missing agreement, visible portal errors, unavailable maximization, or unavailable PDF generation.