check-case-status▌
uscis.gov/check-case-status-or94c8 · updated May 21, 2026
MDX-style export adds YAML metadata + attribution linking explainx.ai and this canonical listing URL.
Look up a USCIS case by 13-character receipt number (e.g. MSC2190012345, EAC2290098765, IOE0123456789) on the modern egov.uscis.gov Next.js portal and return status heading, next-step paragraph, form type (I-130/I-485/N-400/I-765/...), service-center code, last-updated date, and the canonical caseId URL. Read-only.
| name | check-case-status |
| title | USCIS Case Status Lookup |
| description | >- Look up a USCIS case by 13-character receipt number (e.g. MSC2190012345, EAC2290098765, IOE0123456789) on the modern egov.uscis.gov Next.js portal and return status heading, next-step paragraph, form type (I-130/I-485/N-400/I-765/...), service-center code, last-updated date, and the canonical caseId URL. Read-only. |
| website | uscis.gov |
| category | government |
| tags | - uscis - immigration - case-status - read-only - cloudflare - Verified-required |
| source | 'browserbase: agent-runtime 2026-05-16' |
| updated | '2026-05-16' |
| recommended_method | browser |
| alternative_methods | - method: api rationale: >- No public unauthenticated USCIS case-status API exists. The internal `csol-api/case/{receipt}` endpoint that the SPA XHRs to is Cloudflare-blocked from any non-browser caller (verified 403 with --proxies). The legacy `casestatus/displayMyCaseStatus.do?appReceiptNum=...` action endpoint returns 404 — it was removed in the Next.js migration. USCIS does publish a developer Case Status API but it requires an authenticated developer account and is not suitable for ad-hoc lookups. - method: url-param rationale: >- `https://egov.uscis.gov/?caseId={receipt}&localeLang=en` is a valid bookmarkable URL but `caseId` is read CLIENT-SIDE by the SPA — a server-side GET returns the generic landing-form HTML with no status. Useful only for handing the resolved URL to a user. |
| verified | false |
| proxies | true |
USCIS Case Status Lookup
Purpose
Given a 13-character USCIS receipt number (e.g. MSC2190012345, EAC2290098765, IOE0123456789), look it up on the official Case Status Online portal and return: the current case-status heading, the next-step / status-description paragraph, the form type when surfaced (I-130, I-485, N-400, I-765, etc.), the service-center code (derived from the first three letters of the receipt — no scraping needed), the last-updated date when shown, and the canonical case-status URL. Read-only — never logs in, never updates anything, never subscribes.
When to Use
- A user supplies a receipt number ("
MSC2190012345", "my receipt is EAC22...") and wants the current status. - A workflow polls case status over time (rate-limit yourself — see Gotchas).
- An agent needs to disambiguate whether a receipt is on the legacy
.doflow or the modern Next.js portal (this skill always uses the modern path).
Workflow
The portal moved to a Next.js SPA at the root of egov.uscis.gov. The legacy /casestatus/landing.do form action endpoints (displayMyCaseStatus.do, mycasestatus.do) are either gone (404) or Cloudflare-blocked from any non-Verified client (403, Cf-Mitigated: challenge). Use the modern URL https://egov.uscis.gov/?localeLang=en and drive the SPA — there is no public unauthenticated JSON API, and the internal csol-api/case/{receipt} backing endpoint that the SPA XHRs to is Cloudflare-blocked from any out-of-browser caller (verified 403 from browse cloud fetch --proxies).
1. Create a Verified + residential-proxy + captcha-solving session
SID=$(browse cloud sessions create \
--keep-alive \
--verified \
--proxies \
--solve-captchas \
| jq -r '.id')
All three flags are required:
--verified— Cloudflare's managed-challenge engine fingerprints headless Chrome aggressively on this domain. Without it, the SPA shell may load but the moment its client-side JS XHRs tocsol-api/..., Cf responds with a 403 challenge page that breaks the SPA state silently (the form just spins).--proxies— USCIS is unusually aggressive about data-center IP ranges. Bare AWS/GCP/Azure egress trips an immediate 403.--solve-captchas— if Cloudflare elevates to a Turnstile checkbox (rare on the SPA root, common when retrying after a failed lookup), Browserbase's solver handles it. If it elevates to hCaptcha (very rare; observed historically on the legacy.doflow), the same flag handles it.
2. Validate the receipt number locally before opening a session
Format: ^([A-Z]{3})(\d{10})$ (exactly 13 chars)
Parse the prefix into service_center_code immediately — no scraping needed:
| Prefix | Service center |
|---|---|
EAC | Vermont Service Center (Eastern Adjudication Center, St. Albans VT) |
WAC | California Service Center (Western Adjudication Center, Laguna Niguel CA) |
LIN | Nebraska Service Center (Lincoln NE) |
SRC | Texas Service Center (Southern Regional Center, Dallas TX) |
MSC | National Benefits Center (Missouri Service Center, Lee's Summit MO) |
NBC | National Benefits Center (modern label) |
NSC | Nebraska Service Center (modern label, used alongside LIN) |
YSC | Potomac Service Center (Arlington VA) |
IOE | USCIS Electronic Immigration System (ELIS) — online-filed cases, no physical center |
The next two digits are the federal-fiscal-year (21 = FY2021, runs Oct 1 2020 → Sep 30 2021). The next three are a workday index. The last five are the case sequence. Surface these as opaque integers if needed; the FY mapping is the only one worth deriving without extra work.
Reject early any input that doesn't match ^[A-Z]{3}\d{10}$ — emit { "success": false, "error_reasoning": "Invalid receipt format" } without spinning up a session. The submit button on the SPA stays disabled for non-13-char input anyway, so a malformed receipt will hang the click step forever.
3. Open the modern SPA and wait for hydration
browse cloud browse --connect "$SID" open "https://egov.uscis.gov/?localeLang=en"
browse cloud browse --connect "$SID" wait load
browse cloud browse --connect "$SID" wait timeout 2500 # Next.js hydration; the input is in the DOM
# at load time but its React event handlers
# are not attached until hydration completes.
browse cloud browse --connect "$SID" snapshot
The snapshot must show a textbox ref labelled "Enter Another Receipt Number" with placeholder EAC1234567890, and a button ref labelled "Check Status". If the snapshot instead shows a "Just a moment…" body or only a Cloudflare challenge widget, the Verified+proxy combination is failing — see "Cloudflare wall" branch below.
4. Type the receipt and confirm the button enables
browse cloud browse --connect "$SID" fill @receipt_number "$RECEIPT"
browse cloud browse --connect "$SID" wait timeout 500
browse cloud browse --connect "$SID" snapshot
After 13 valid characters land in the input, the initCaseSearch button transitions out of disabled. Verify the snapshot shows it un-disabled before clicking. If it's still disabled after typing, the React controlled-input event didn't fire — re-snapshot, get the latest ref, and re-fill (do not type per-character; the spinner-styling masking in the input's CSS class can drop keystrokes when typed too fast).
5. Submit and wait for the in-place result render
browse cloud browse --connect "$SID" click @initCaseSearch
browse cloud browse --connect "$SID" wait timeout 4000 # XHR to csol-api/case/{receipt} round-trip
browse cloud browse --connect "$SID" snapshot
The page does not navigate — the URL stays at https://egov.uscis.gov/?localeLang=en (it may pick up &caseId={receipt} via history.replaceState, but the path doesn't change). The <div class="caseStatus-container"> block re-renders in place. Don't poll the URL; poll the snapshot for either the status heading or a known not-found / error string.
6. Branch on what the result block shows
- Status heading + paragraph rendered → success path. Extract the heading (an
h1/h2in the container) and the paragraph beneath it. The paragraph almost always opens with"On <Month Day, Year>, we <verb> your Form <type>…"— regex that forform_typeandlast_updated:form_type:/\bForm (I-\d{3}[A-Z]?|N-\d{3}|G-\d{3}|FOIA|EOIR-\d+)\b/last_updated:/^On ([A-Z][a-z]+ \d{1,2}, \d{4}),/m
- "Receipt Number Can Not Be Found" or "Your case status could not be found" → emit
{ success: true, status: "Not Found", status_description: <verbatim site text>, form_type: null, last_updated: null }. This is a legitimate outcome, not an error. - "Validation Error" / "Please enter a valid receipt number" → the SPA's client-side check rejected the input. Should never happen if step 2's regex passed; if it does, treat as
{ success: false, error_reasoning: "USCIS-side validation rejected receipt" }. - Cloudflare wall — snapshot shows a Turnstile widget, "Just a moment…", or a
cf-mitigatedbody, or the result container never updates after 15s → emit{ success: false, error_reasoning: "Cloudflare challenge — not bypassed" }. Recreate the session with--solve-captchasif not already set, optionally--region us-east-1to swap the proxy egress region, and retry once. After two consecutive Cf walls, give up and surface the error — do not loop.
7. Construct the canonical URL
case_status_url = "https://egov.uscis.gov/?caseId=" + receipt + "&localeLang=en"
This is the link a user can paste into a fresh browser to reproduce the lookup. The caseId param is read client-side by the SPA on load.
8. Release the session
browse cloud sessions update "$SID" --status REQUEST_RELEASE
Site-Specific Gotchas
- Use
https://egov.uscis.gov/?localeLang=en, NOT/casestatus/landing.do. The legacy.doURL still exists but every request to it returns403 Cf-Mitigated: challengeregardless of Verified/proxy flags — Cloudflare treats it as a deprecated honeypot path. The modern Next.js SPA at the root is the only working entry. Confirmed 2026-05-16: legacylanding.do403 even with--proxies --allow-redirects; modern/?localeLang=en200 from the same fetcher. - Primary anti-bot is Cloudflare's managed challenge, NOT hCaptcha. Task-prompt assumptions notwithstanding, evidence is
Server: cloudflare,Cf-Mitigated: challenge, JS-challenge body with__cf_chl_tk+__cf_chl_rt_tktokens. hCaptcha may appear as a Cloudflare escalation on retries —--solve-captchascovers both. Don't waste time looking for an hCaptcha sitekey at first contact. - The internal
csol-api/case/{receipt}backing endpoint is Cf-blocked. Verified 403 frombrowse cloud fetch --proxies --allow-redirectson bothcsol-api/case/{receipt}andcsol-api/cases/{receipt}(plural). The 403 status (vs 404) confirms the path exists but is firewalled — do not try to hit it directly even with a Browserbase Function or curl. The SPA is the only way in. Also tested-blocked:egov/api/casestatus/{receipt}(403). Definitely-non-existent:casestatus/displayMyCaseStatus.do?appReceiptNum=...(404),api/casestatus?receiptNumber=...(404). Don't probe further. ?caseId=...is read client-side only. GETtinghttps://egov.uscis.gov/?caseId=MSC2190012345&localeLang=enreturns the same generic landing-form HTML as/?localeLang=enwith no server-rendered status. The SPA readscaseIdfromwindow.location.searchafter hydration and then fires the XHR. Server-side scraping by URL won't work.- The Check Status button is
disableduntil exactly 13 chars are typed. The receipt input hasmaxLength="13". The button's enabled state is React-controlled —fillwill fire the input event correctly; per-charactertypecan race the spinner-styling masking class. Always snapshot-verify the button is un-disabled before clicking, otherwise the click is a no-op. - The lookup result renders in place — no navigation. URL stays at
/?localeLang=en(possibly with&caseId=appended viahistory.replaceState). Wait for the.caseStatus-containerDOM mutation, not a page load. ~3–5s wall after click is typical; budget 8s before declaring failure. - Status-description text is the primary source of truth for
form_typeandlast_updated. USCIS does NOT expose form type as a structured field on the result page — it's embedded in the paragraph:"On January 15, 2024, we received your Form I-130, Petition for Alien Relative…". Regex it out. Same for the date. If the form type isn't in the paragraph (rare — happens on someIOEELIS cases that pre-date the form-name templating), emitform_type: nullrather than guessing from the receipt prefix. IOE(ELIS) receipts may be longer than 13 characters in some historical exports (sometimes seen as 13–15). The modern SPA's input is hard-capped atmaxLength="13", so anything longer will be truncated client-side. If your input is a 14- or 15-charIOEstring, drop trailing chars to fit 13 only if the trailing chars are zeros; otherwise reject as malformed.- Service-center codes are not always present in the URL after submit. Parse them from the receipt prefix locally (see Workflow step 2 table). Do not try to extract them from the result page — USCIS surfaces the office name in the status paragraph sometimes ("at our National Benefits Center"), but it's an inconsistent natural-language mention, not a reliable field.
- Rate-limit yourself to ≤ 1 lookup / 5 seconds across a session. USCIS doesn't publish a limit, but Cloudflare's challenge engine elevates after ~10 rapid lookups from the same session, and the elevation can persist across session renewal from the same proxy IP for ~15 minutes. For bulk lookups, rotate proxy egress (
--region us-east-1/us-west-2/eu-central-1round-robin) and add a 5–8s sleep between receipts. - Don't reuse a session across many lookups. Recreate the session every ~5 lookups even if it stayed healthy. Long-lived sessions accumulate Cloudflare cookies (
__cf_bm,__cflb) that eventually trip the challenge engine when their fingerprint drifts from the proxy fingerprint. - READ-ONLY. There are no buttons to click that would mutate state on this page (no login required for the lookup), but do not click the "Login" button or the "Sign up for Case Status Online" CTA — both lead into the MyAccount flow which is an entirely different skill scope.
localeLang=esis the Spanish UI. Same SPA, samecsol-apibacking endpoint, but all status text comes back translated (e.g."Caso fue recibido"instead of"Case Was Received"). Always pinlocaleLang=enfor consistent text extraction.
Expected Output
Five distinct outcome shapes.
// 1. Found — status retrieved successfully
{
"success": true,
"receipt_number": "MSC2190012345",
"service_center_code": "MSC",
"service_center_name": "National Benefits Center",
"status": "Case Was Received",
"status_description": "On January 15, 2024, we received your Form I-130, Petition for Alien Relative, Receipt Number MSC2190012345, and mailed you a receipt notice that describes how we will process your case. Please follow any instructions in the notice. If you do not receive your receipt notice by February 15, 2024, please call Customer Service at 1-800-375-5283.",
"form_type": "I-130",
"last_updated": "January 15, 2024",
"case_status_url": "https://egov.uscis.gov/?caseId=MSC2190012345&localeLang=en",
"error_reasoning": null
}
// 2. Not found — receipt is well-formed but USCIS has no record
{
"success": true,
"receipt_number": "EAC9999999999",
"service_center_code": "EAC",
"service_center_name": "Vermont Service Center",
"status": "Not Found",
"status_description": "Validation Error: This receipt number does not exist in our database, or it has not been updated recently. Please re-check that you have entered the correct receipt number from your USCIS receipt notice and try again.",
"form_type": null,
"last_updated": null,
"case_status_url": "https://egov.uscis.gov/?caseId=EAC9999999999&localeLang=en",
"error_reasoning": null
}
// 3. Invalid format — rejected pre-session (no Browserbase cost)
{
"success": false,
"receipt_number": "ABC123",
"service_center_code": null,
"service_center_name": null,
"status": null,
"status_description": null,
"form_type": null,
"last_updated": null,
"case_status_url": null,
"error_reasoning": "Invalid receipt format — expected 3 uppercase letters followed by 10 digits (e.g. EAC1234567890)."
}
// 4. Cloudflare wall — anti-bot not bypassed even with Verified + proxies + captcha solver
{
"success": false,
"receipt_number": "MSC2190012345",
"service_center_code": "MSC",
"service_center_name": "National Benefits Center",
"status": null,
"status_description": null,
"form_type": null,
"last_updated": null,
"case_status_url": "https://egov.uscis.gov/?caseId=MSC2190012345&localeLang=en",
"error_reasoning": "Cloudflare challenge — not bypassed. Tried --verified + --proxies + --solve-captchas across 2 sessions; result container never populated within 15s of submit and snapshot showed Turnstile widget."
}
// 5. Approved / other state — same shape as #1, just different status heading + paragraph
{
"success": true,
"receipt_number": "LIN2090012345",
"service_center_code": "LIN",
"service_center_name": "Nebraska Service Center",
"status": "Case Was Approved",
"status_description": "On March 3, 2024, we approved your Form I-765, Application for Employment Authorization, Receipt Number LIN2090012345. We will mail your approval notice. Please follow any instructions in the notice. If you move, go to www.uscis.gov/addresschange to give us your new mailing address.",
"form_type": "I-765",
"last_updated": "March 3, 2024",
"case_status_url": "https://egov.uscis.gov/?caseId=LIN2090012345&localeLang=en",
"error_reasoning": null
}
How to use check-case-status on Cursor
AI-first code editor with Composer
Prerequisites
Before installing skills in Cursor, ensure your development environment meets these requirements:
- ›Cursor installed and configured on your development machine
- ›Node.js version 16.0+ with npm package manager (verify with
node --version) - ›Active project directory or workspace where you want to add check-case-status
Execute installation command
Execute the skills CLI command in your project's root directory to begin installation:
The skills CLI fetches check-case-status from GitHub repository uscis.gov/check-case-status-or94c8 and configures it for Cursor.
Select Cursor when prompted
The CLI will show a list of available agents. Use arrow keys to navigate and space to select Cursor:
Verify installation
Confirm successful installation by checking the skill directory location:
Reload or restart Cursor to activate check-case-status. Access the skill through slash commands (e.g., /check-case-status) or your agent's skill management interface.
Security & Verification Notice
We perform automated surface-level scans (Gen AI Scanner, Socket, Snyk) during installation. These checks detect common vulnerabilities but do not guarantee complete security. Always review skill source code and verify the publisher's reputation before production use.
Skills execute code in your development environment. Always verify the publisher's identity, review recent commits, and test in isolated environments before production deployment.
List & Monetize Your Skill
Submit your Claude Code skill and start earning
Use Cases▌
Task Automation & Efficiency
Automate repetitive workflows and reduce manual effort
Example
Generate reports, summarize documents, draft communications
Save 3-5 hours per week on routine tasks
Knowledge Enhancement
Learn new skills, understand complex topics, get expert guidance
Example
Explain concepts, provide examples, suggest learning resources
Accelerate learning and skill development by 2x
Quality Improvement
Enhance output quality through reviews, suggestions, and refinements
Example
Review drafts, suggest improvements, catch errors
Improve work quality by 30-40% with less effort
Implementation Guide▌
Prerequisites
- ›Claude Desktop or compatible AI client with skill support
- ›Clear understanding of task or problem to solve
- ›Willingness to iterate and refine outputs
Time Estimate
15-45 minutes depending on use case complexity
Installation Steps
- 1.Install skill using provided installation command
- 2.Test with simple use case relevant to your work
- 3.Evaluate output quality and relevance
- 4.Iterate on prompts to improve results
- 5.Integrate into regular workflow if valuable
Common Pitfalls
- ⚠Expecting perfect results without iteration
- ⚠Not providing enough context in prompts
- ⚠Using skill for tasks outside its intended scope
- ⚠Accepting outputs without review and validation
Best Practices▌
✓ Do
- +Start with clear, specific prompts
- +Provide relevant context and constraints
- +Review and refine all outputs before using
- +Iterate to improve output quality
- +Document successful prompt patterns
✗ Don't
- −Don't use without understanding skill limitations
- −Don't skip validation of outputs
- −Don't share sensitive information in prompts
- −Don't expect skill to replace human judgment
💡 Pro Tips
- ★Be specific about desired format and style
- ★Ask for multiple options to choose from
- ★Request explanations to understand reasoning
- ★Combine AI efficiency with human expertise
When to Use This▌
✓ Use When
Use when skill capabilities match your task, clear ROI on time saved, and you can validate outputs. Best for repetitive tasks, learning, and quality improvement.
✗ Avoid When
Avoid when task requires deep expertise you can't validate, involves sensitive decisions, or when learning process is more valuable than speed of completion.
Learning Path▌
- 1Familiarize yourself with skill capabilities and limitations
- 2Start with low-risk, non-critical tasks
- 3Progress to more complex and valuable use cases
- 4Build expertise through regular use and experimentation
Discussion
Product Hunt–style comments (not star reviews)- No comments yet — start the thread.
Ratings
4.7★★★★★69 reviews- ★★★★★Kofi Sanchez· Dec 28, 2024
Useful defaults in check-case-status — fewer surprises than typical one-off scripts, and it plays nicely with `npx skills` flows.
- ★★★★★Ren Reddy· Dec 28, 2024
Solid pick for teams standardizing on skills: check-case-status is focused, and the summary matches what you get after install.
- ★★★★★Soo Perez· Dec 24, 2024
Registry listing for check-case-status matched our evaluation — installs cleanly and behaves as described in the markdown.
- ★★★★★Pratham Ware· Dec 16, 2024
check-case-status has been reliable in day-to-day use. Documentation quality is above average for community skills.
- ★★★★★Lucas Okafor· Dec 8, 2024
We added check-case-status from the explainx registry; install was straightforward and the SKILL.md answered most questions upfront.
- ★★★★★Lucas Gupta· Dec 4, 2024
check-case-status reduced setup friction for our internal harness; good balance of opinion and flexibility.
- ★★★★★Isabella Nasser· Nov 27, 2024
Keeps context tight: check-case-status is the kind of skill you can hand to a new teammate without a long onboarding doc.
- ★★★★★Kofi Li· Nov 23, 2024
Registry listing for check-case-status matched our evaluation — installs cleanly and behaves as described in the markdown.
- ★★★★★Neel Brown· Nov 19, 2024
check-case-status has been reliable in day-to-day use. Documentation quality is above average for community skills.
- ★★★★★Lucas Patel· Nov 15, 2024
check-case-status is among the better-maintained entries we tried; worth keeping pinned for repeat workflows.
showing 1-10 of 69