
Aloísio Vítor
Image Processing Expert

Immigration case status data extraction can reduce repetitive checks for legal teams, mobility providers, and applicants, but it must be designed around consent, privacy, and human oversight. The correct architecture does not give an AI agent unrestricted access to government portals. Instead, a secure service receives an authorized case identifier, retrieves the minimum status data through an approved channel, records source evidence, detects meaningful changes, and sends a structured event to the AI workflow. CAPTCHA handling is only a recovery step for permitted browser sessions, never a substitute for authorization. This guide presents a practical design for status monitoring, receipt-number protection, page parsing, CapSolver integration, alert classification, audit logs, and escalation rules suitable for supervised legal operations.
A case-monitoring service should answer a narrow question: “Has the status of this authorized case changed?” It should not search for unrelated individuals, infer protected characteristics, or make legal conclusions from a short portal message.
The USCIS Case Status Online tool uses a unique 13-character receipt number consisting of three letters and ten numbers. Treat that identifier as sensitive operational data even when it is not a password. The USCIS case-status guidance explains how applicants can check an application, petition, or request.
Before collection, require:
The CapSolver AI and automation FAQ is helpful when defining what the model should decide versus what deterministic tools should execute.
Store only what the workflow needs. A useful record includes a pseudonymous internal matter ID, protected receipt number reference, normalized status, raw status text, source, and timestamps.
from dataclasses import dataclass
from datetime import datetime, timezone
@dataclass
class ImmigrationCaseStatus:
matter_id: str
receipt_number_ref: str
status_code: str
status_title: str
status_message: str
source_url: str
checked_at: str
source_updated_at: str | None = None
def utc_now() -> str:
return datetime.now(timezone.utc).isoformat()
Do not place the full receipt number in model prompts, logs, analytics events, or error trackers. Store the encrypted value in a secrets service and send the retrieval worker only a short-lived reference.
Start with official notifications, online-account access, and approved data feeds. Browser automation should be the last structured option, not the default.
| Collection channel | Recommended use | Privacy exposure | Operational reliability |
|---|---|---|---|
| Official account notification | Applicant-driven alerts | Low | High |
| Approved API or case-management integration | Authorized portfolio monitoring | Low to medium | High |
| User-provided export or notice | One-time evidence ingestion | Medium | High |
| Authorized browser status check | Limited fallback | Medium | Medium |
| Uncontrolled scraping | Not recommended | High | Low |
The official USCIS status-check instructions should be the primary operational reference. For timing context, the USCIS processing-times tool provides separate estimates; do not treat an estimate as a case-specific promise.
Validate format before starting a browser session. This reduces unnecessary requests and prevents malformed input from reaching the portal.
import re
RECEIPT_PATTERN = re.compile(r"^[A-Z]{3}[0-9]{10}$")
def normalize_receipt_number(value: str) -> str:
normalized = value.replace("-", "").replace(" ", "").upper()
if not RECEIPT_PATTERN.fullmatch(normalized):
raise ValueError("Receipt number must contain three letters and ten digits")
return normalized
Return generic validation errors to the user. Avoid echoing the full receipt number in stack traces or support tickets.
The browser worker should be isolated from the language model. It receives an authorized identifier reference, retrieves the encrypted value, performs the check, and emits a sanitized result.
from playwright.async_api import Page
CASE_STATUS_URL = "https://egov.uscis.gov/"
async def fetch_status_page(page: Page, receipt_number: str) -> dict:
await page.goto(CASE_STATUS_URL, wait_until="domcontentloaded")
# Selectors must be verified against the current authorized page.
await page.get_by_label("Enter a Receipt Number").fill(receipt_number)
await page.get_by_role("button", name="Check Status").click()
await page.wait_for_load_state("networkidle")
title = await page.locator("main h1, main h2").first.inner_text()
message = await page.locator("main").inner_text()
return {
"status_title": title.strip(),
"status_message": message.strip(),
"source_url": page.url,
}
Selectors and page behavior can change. Test against a permitted staging or controlled workflow, monitor parser failures, and route unexpected layouts to human review instead of letting the model guess.
The CapSolver Python web-scraping guide covers robust browser and parsing practices, while the CapSolver web-scraping FAQ addresses common automation reliability questions.
If an authorized browser session presents a supported CAPTCHA, use the CapSolver Core browser methods described in the user-provided AI Agent documentation. The model should not receive the receipt number, browser cookies, or CapSolver key.
import os
from capsolver_core import Capsolver
cap = Capsolver(
api_key=os.environ["CAPSOLVER_API_KEY"],
default_timeout=180,
)
async def resolve_supported_challenge(page: Page) -> dict:
detected = await cap.detect(page)
if not detected:
return {"handled": False, "reason": "No supported challenge detected"}
solution = await cap.solve_on_page(page)
return {
"handled": True,
"solution": solution,
}
Keep retries bounded. A safe worker can attempt the status lookup, invoke the challenge handler once if needed, then retry the original action. If the challenge repeats, stop and request operator review.
async def authorized_status_check(page: Page, receipt_number: str) -> dict:
try:
return await fetch_status_page(page, receipt_number)
except Exception as first_error:
recovery = await resolve_supported_challenge(page)
if not recovery["handled"]:
raise first_error
return await fetch_status_page(page, receipt_number)
The CapSolver CAPTCHA-solving FAQ explains supported challenge workflows. For troubleshooting, use the CapSolver errors FAQ.
Bonus Code: Use code WEBS at CapSolver Dashboard to get an extra 5% bonus on every recharge.
Portal messages are written for applicants, not machine classification. Preserve the complete source text and map only high-level workflow categories.
STATUS_RULES = {
"case was received": "received",
"case is being actively reviewed": "under_review",
"request for evidence": "evidence_requested",
"case was approved": "approved",
"card was produced": "document_produced",
"case was denied": "adverse_decision",
}
def classify_status(title: str, message: str) -> dict:
combined = f"{title} {message}".lower()
for phrase, code in STATUS_RULES.items():
if phrase in combined:
return {"status_code": code, "confidence": "rule_match"}
return {"status_code": "unclassified", "confidence": "needs_review"}
Rules should trigger workflow actions, not legal conclusions. For example, evidence_requested can create a review task, but only a qualified professional should interpret the request and advise the applicant.
Compare normalized fields and a hash of the source message. Alert only when the status code or substantive text changes.
import hashlib
def status_fingerprint(status: dict) -> str:
canonical = "|".join([
status.get("status_code", ""),
status.get("status_title", "").strip(),
status.get("status_message", "").strip(),
])
return hashlib.sha256(canonical.encode("utf-8")).hexdigest()
def has_changed(previous: dict | None, current: dict) -> bool:
if previous is None:
return True
return status_fingerprint(previous) != status_fingerprint(current)
Use a risk-based schedule rather than constant polling. Many workflows need daily or weekly checks, not minute-by-minute requests. Respect portal limits and pause jobs during incidents or unexpected challenge spikes.
The AI agent should receive a redacted event object that is safe to summarize.
SAFE_EVENT = {
"matter_id": "MAT-2026-00172",
"previous_status": "under_review",
"current_status": "evidence_requested",
"change_detected_at": "2026-08-25T08:15:00Z",
"source": "official_case_status_portal",
"recommended_action": "create_human_review_task",
}
A suitable system instruction is: “Summarize the detected change, cite the source timestamp, and create a review checklist. Do not provide legal advice, predict the outcome, or contact the government or applicant without approval.”
For agent architecture ideas, see the CapSolver AI blog and CapSolver automation resources.
Immigration matters can contain highly sensitive personal information. Apply encryption in transit and at rest, least-privilege access, staff authentication, tenant isolation, audit logging, deletion schedules, and incident response. The USCIS website policies and the portal's privacy notices should be reviewed before implementation.
Do not collect statuses for people who have not authorized the service. Do not infer nationality, health, religion, family circumstances, or employment eligibility beyond verified records and the approved purpose. Do not train a general model on receipt numbers or case histories. Consult qualified counsel for jurisdiction-specific legal and privacy requirements.
| Control area | Minimum production requirement |
|---|---|
| Authorization | Written client or applicant consent linked to the matter ID |
| Secrets | Receipt number encrypted and referenced by token |
| Collection | Official channels first; browser fallback only if permitted |
| CAPTCHA | Deterministic handler, one bounded retry, no secrets in prompts |
| Parsing | Raw text preserved; unexpected layouts go to review |
| AI output | Summary and task routing only, not legal advice |
| Retention | Matter-based deletion policy and auditable access history |
Immigration case status data extraction should be built as a secure evidence service, not an autonomous legal decision-maker. Protect receipt numbers, use official channels first, isolate browser execution, preserve source text, and send the AI agent only a redacted change event. When a permitted browser session encounters a supported CAPTCHA, CapSolver can provide a controlled recovery step while the rest of the system maintains authorization, privacy, and auditability.
Start with CapSolver in a controlled test environment, then complete privacy, security, terms, and legal review before monitoring real cases.
No. Monitor only cases for which the applicant or authorized client has given permission and your organization has a documented lawful purpose.
Availability differs by agency and program. Prefer official account notifications, approved integrations, or user-provided records. Do not assume a web page permits automated collection.
No. Keep the full identifier inside the protected retrieval service. Send the model a pseudonymous matter ID and redacted status event.
Stop after a bounded recovery attempt and request human review. Repeated challenges can indicate a session, rate, policy, or technical problem that automation should not ignore.
It can summarize the official text and create a review task, but legal interpretation, deadlines, responses, and applicant communications should be handled or approved by a qualified professional.
Learn scalable Rust web scraping architecture with reqwest, scraper, async scraping, headless browser scraping, proxy rotation, and compliant CAPTCHA handling.

Learn the best techniques to scrape job listings without getting blocked. Master Indeed scraping, Google Jobs API, and web scraping API with CapSolver.
