Automate AIS US Visa Information appointment scheduling for a supplied locale, credentials, date range, and optional appointment constraints.
Use Cases
Use when an AIS NIV applicant must authenticate, handle the site's browser challenge, inspect appointment availability, and submit a booking for a slot in a caller-specified date interval.
Automation Flow
- Build the locale-specific sign-in URL directly:
https://ais.usvisa-info.com/{locale}/niv/users/sign_in(the observed Canadian locale is{locale}=en-ca). Navigate there withwaitUntil: "domcontentloaded". - Immediately invoke the Browserless challenge solver with
solve({wait:false, timeout:30000}); the AIS page may remain inaccessible until this completes. - Fill the sign-in form using the page's email and password inputs, then submit. Supply credentials only through runtime variables such as
{email}and{password}; never place them in the skill. - If a terms/consent checkbox or acceptance control is shown, accept it before continuing. Locate the appointment-scheduling link or button from the authenticated page rather than guessing an opaque appointment URL, then follow it.
- On the scheduling page, use the page's date and time controls to inspect dates from
{start-date}through{end-date}inclusive. Prefer the site's calendar controls and available-slot elements; do not treat disabled dates or unavailable times as slots. - Select the first slot satisfying the caller's optional constraints, verify that the displayed date/time and applicant details are correct, and submit the booking. If no qualifying slot exists, return an explicit no-availability result instead of submitting.
- After navigation to the confirmation state, run this evaluator on the loaded scheduling or confirmation page to capture the visible appointment data:
(() => {
const text = (el) =>
(el?.innerText || el?.value || el?.getAttribute("aria-label") || "")
.replace(/\s+/g, " ")
.trim();
const available = (el) => {
const control = el.matches("option") ? el.parentElement : el;
if (!control) return false;
const blocked = (node) =>
node.matches(
'[disabled], [hidden], [aria-disabled="true"], .disabled, .unavailable, .ui-datepicker-unselectable',
) ||
node.closest(
'fieldset:disabled, optgroup:disabled, [hidden], [aria-disabled="true"], .disabled, .unavailable, .ui-datepicker-unselectable',
);
if (blocked(el) || blocked(control)) return false;
const style = getComputedStyle(control);
return (
style.display !== "none" &&
style.visibility !== "hidden" &&
control.getClientRects().length > 0
);
};
const dateNodes = [
...document.querySelectorAll(
'input[id*="appointment_date"], input[name*="appointment_date"], [data-date], td.available, button.available, .ui-datepicker-calendar td',
),
].filter(available);
const timeNodes = [
...document.querySelectorAll(
'select[id*="appointment_time"], select[name*="appointment_time"], option:not([disabled]), [data-time], .appointment-time, .time-slot',
),
].filter(available);
const confirmation = [
...document.querySelectorAll(
'h1,h2,h3,.confirmation,.appointment-details,[class*="confirmation"],[class*="appointment"]',
),
]
.map(text)
.filter(Boolean);
return {
url: location.href,
dateControls: dateNodes
.map((el) => ({
text: text(el),
date: el.getAttribute("data-date") || el.value || null,
}))
.filter((x) => x.text || x.date),
timeControls: timeNodes
.map((el) => ({
text: text(el),
time: el.getAttribute("data-time") || el.value || null,
}))
.filter((x) => x.text || x.time),
confirmation,
};
})();Possible Friction Points
- The known entry point is the locale-scoped path
/en-ca/niv/users/sign_in; substitute the caller's locale rather than using the site root. - The run required Browserless
solve(wait:false, timeout:30000)before authenticated interaction; invoke it at the sign-in page. - Appointment and confirmation URLs were not exposed by the observed run, so do not invent an opaque ID-bearing URL. Resolve the scheduling control after login.
- Availability calendars commonly contain disabled dates and multiple row/control types; extract only enabled controls and validate the selected date against both inclusive range boundaries.
- Booking is an external side effect. Confirm the selected date, time, location, and applicant before the final submit action.