# USCIS Processing Time Monitor (`nerolabs/uscis-processing-time-monitor`) Actor

Look up and monitor official USCIS case processing times for any form, category and office, and get USCIS's own answer on whether a case is outside normal processing time yet so an inquiry can be filed.

- **URL**: https://apify.com/nerolabs/uscis-processing-time-monitor.md
- **Developed by:** [Adam Pearce](https://apify.com/nerolabs) (community)
- **Categories:** Business, Automation, Agents
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $20.00 / 1,000 processing-time lookups

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

Waiting on a USCIS case and tired of re-checking the processing times page by hand? **This Actor reads the official USCIS Case Processing Times tool for you**, for any form, category and office, tells you whether a specific case is far enough along to file an inquiry, and can watch a whole caseload and alert you the moment USCIS moves its own numbers.

It reads [egov.uscis.gov/processing-times](https://egov.uscis.gov/processing-times), the same official source a paralegal would open in a browser, and returns it as clean structured data you can schedule, pipe into a spreadsheet, or call from an API or an AI agent.

### What makes this different from a plain lookup

Most tools hand you a number. This one answers the two questions that actually cause work in an immigration practice:

1. **"Can we file an inquiry on this case yet?"** Give it a case receipt date and it returns **USCIS's own answer**: either the case is outside normal processing time and can be queried now, or the exact date from which it can. That is not an estimate or a guess based on averages, it is the same answer the official tool gives.
2. **"Did anything move?"** USCIS republishes these figures monthly and they shift. Monitor mode remembers what it saw last time and reports only genuine movement, so a scheduled run is a short list of what changed rather than a wall of numbers to re-read.

### What you can do with it

- Watch every form, category and office combination across your active caseload, and get told when a queue speeds up or slows down.
- Catch the moment a client's case crosses into inquiry-eligible territory, instead of checking receipt dates by hand each month.
- Track the same form across different field offices to see where cases are actually moving faster.
- Feed current, structured processing times into a client portal, a case-management system, or an AI assistant.

### How to use it

1. **Start with reference mode.** Set `listAvailableOptions` to true and run it. USCIS uses codes that nobody can guess, such as `134A-IR` for "U.S. citizen filing for a spouse, parent, or child under 21", and `SCD` for Service Center Operations. This mode lists all 44 forms with their category codes, and it is **never charged**. Add a form number to also get that form's office codes.
2. **Do a lookup.** Put the form number, category code and office code in, and run it.
3. **Add a receipt date** (in `YYYY-MM-DD` format) to also get the inquiry-eligibility answer for that specific case.
4. **Watch a caseload.** Put all your combinations in the `targets` array, turn on `monitorMode`, and schedule it monthly. The first run records a baseline, and every run after it reports only what changed.

### Input

| Field | What it does |
|---|---|
| `listAvailableOptions` | Reference mode: lists valid form, category and office codes. Never charged. |
| `formName` | Form number, e.g. `I-130`, `N-400`, `I-485`, `I-765`. |
| `formCategory` | Category code for that form, e.g. `134A-IR`. |
| `officeCode` | Office code, e.g. `SCD`, `NBC`, `FOD`, or a field office like `NYC`. |
| `receiptDate` | Optional case receipt date in `YYYY-MM-DD`. Adds the inquiry-eligibility answer. |
| `targets` | An array of combinations to check in one run, each with an optional `label` and `receiptDate`. |
| `monitorMode` | Report only what changed since the last run. |
| `watchlistId` | Keeps separate monitor histories apart, one per client list or schedule. |

### Output

```json
{
  "label": "Nguyen family petition",
  "formName": "I-130",
  "formCategory": "134A-IR",
  "officeCode": "SCD",
  "formDescription": "Petition for Alien Relative",
  "categoryDescription": "U.S. citizen filing for a spouse, parent, or child under 21",
  "found": true,
  "rangeLower": 21.5,
  "rangeUpper": 29,
  "rangeUnit": "Months",
  "rangeText": "21.5 to 29 Months",
  "serviceRequestDate": "March 18, 2024",
  "publicationDate": "July 15, 2026",
  "dataPeriod": "Processing Time Data from January 2025 to June 2026",
  "receiptDate": "2019-01-15",
  "canSubmitInquiryNow": true,
  "earliestInquiryDate": null,
  "inquiryLink": "https://egov.uscis.gov/e-request/onpt",
  "changeDetected": true,
  "changeSummary": "Processing time is now 21.5 to 29 Months, was 18 to 33 Months (faster).",
  "sourceUrl": "https://egov.uscis.gov/processing-times"
}
```

You can download the dataset as JSON, CSV, Excel or HTML.

#### Main fields

| Field | Meaning |
|---|---|
| `rangeText` | The published processing time, e.g. "21.5 to 29 Months". |
| `rangeLower` / `rangeUpper` | The same range as numbers, for sorting and charting. |
| `serviceRequestDate` | Cases receipted on or before this date are outside normal processing time. |
| `canSubmitInquiryNow` | Whether the case you gave a receipt date for can be queried now. |
| `earliestInquiryDate` | If not yet, the date from which it can be. |
| `changeDetected` / `changeSummary` | What moved since the last run, in Monitor mode. |
| `found` | False when USCIS publishes nothing for that combination. |
| `notes` | Why a row is empty or an input was ignored. Never left to guesswork. |

### How much does it cost?

Every run has to open a real browser session and clear the anti-bot check on the USCIS site before any lookup can happen. That cost is the same whether you check one combination or fifty, which is why there is a small **run-start charge** alongside the per-result charges.

**The practical consequence: put all your checks in one run.** Checking 30 combinations in a single run costs a fraction of running the Actor 30 separate times.

| Event | Price |
|---|---|
| Run start | $0.01 per GB of memory |
| Processing-time lookup | $0.02 |
| Case inquiry-eligibility check | $0.03 |
| Monitor mode: change detected | $0.05 |
| Monitor mode: no change confirmed | $0.006 |

A realistic example: watching **30 combinations once a month** in Monitor mode, with a couple of them moving, costs roughly **$0.30 per month**. Reference mode, which you will use to look up codes, is free.

### Tips

- Batch everything into the `targets` array rather than running the Actor repeatedly. It is the single biggest thing you can do to keep the cost down.
- Use a distinct `watchlistId` per schedule, so two schedules do not overwrite each other's baseline.
- Run it monthly. USCIS updates these figures monthly, so anything more frequent mostly pays to confirm nothing changed.
- Receipt dates must be `YYYY-MM-DD`. Other formats are rejected with an explanation rather than silently ignored.

### FAQ

**Is this official USCIS data?**
Yes. It comes from the USCIS Case Processing Times tool. This Actor is not affiliated with or endorsed by USCIS or DHS, and uses none of their branding.

**Is this legal?**
The data is published by a U.S. federal agency and is in the public domain under 17 U.S.C. §105. The USCIS site's `robots.txt` disallows nothing, and neither USCIS's website policies nor DHS's terms of use restrict reading or reusing this information, including commercially. The Actor only reads public pages and never attempts to log in or access anyone's personal case record.

**Can it track my individual case status?**
No, and nothing can do that without your account. This works on the *published* processing times, plus the official inquiry-eligibility answer for a given receipt date. Personal case status is not available through any public interface.

**Why do I need a category code and an office code?**
Because USCIS publishes different times for each. An I-130 filed by a U.S. citizen for a spouse is a different queue from one filed for a sibling, and an N-400 in New York is a different queue from one in Los Angeles. Run reference mode to see the valid codes.

**A combination returns nothing. Is it broken?**
USCIS does not publish a figure for every possible combination. When that happens you get `found: false` and a note saying so, rather than a blank row. Check your codes with reference mode.

**Why doesn't a new publication date count as a change?**
USCIS re-publishes monthly whether or not the numbers move. Treating that alone as a change would mean an alert every single month telling you nothing useful, so Monitor mode reports the date but only flags a real movement.

### Support

Found a problem, or want a form or field covered that is not here yet? Open an issue on the Issues tab and I will reply personally.

If this saved you a manual check of the USCIS processing-times page, a review helps a lot and helps decide what to build next.

# Actor input Schema

## `listAvailableOptions` (type: `boolean`):

Turn this on to get the codes the other modes need. On its own it lists all 44 USCIS forms with their category codes. Combine it with a Form number below to also get that form's office codes. This mode is never charged.

## `formName` (type: `string`):

USCIS form number exactly as published, for example I-130, N-400, I-485, I-765. Use reference mode above to see the full list.

## `formCategory` (type: `string`):

The category (subtype) code for the form, for example 134A-IR for a U.S. citizen filing for a spouse, parent or child under 21. These codes are not guessable, use reference mode to find the right one.

## `officeCode` (type: `string`):

The processing office code, for example SCD (Service Center Operations), NBC (National Benefits Center), FOD (All Field Offices), or a specific field office such as NYC. Use reference mode to find valid codes for your form.

## `receiptDate` (type: `string`):

The receipt date printed on the USCIS receipt notice, in YYYY-MM-DD format. When supplied, the result also includes USCIS's own answer on whether this case is outside normal processing time and a case inquiry can be submitted now, or the exact date from which it can. Leave empty for a plain processing-time lookup.

## `targets` (type: `array`):

Check many form/category/office combinations in one run. Each entry takes formName, formCategory and officeCode, plus an optional label and an optional receiptDate (YYYY-MM-DD). Cheaper and faster than one run per case, because the browser session is shared across all of them.

## `monitorMode` (type: `boolean`):

Compare each combination against the figures seen on the previous run and report only real movement: the processing-time range moving, the inquiry-eligibility date shifting, a figure being suppressed or published again, or a tracked case becoming eligible for an inquiry. Schedule this monthly, USCIS republishes monthly. The first run records a baseline.

## `watchlistId` (type: `string`):

Keeps separate monitor histories apart. Use a different ID per client list or per schedule so their baselines don't overwrite each other.

## `proxyConfiguration` (type: `object`):

USCIS sits behind Cloudflare. The default (US residential) is the setting confirmed to work; change it only if you have a reason to.

## Actor input object example

```json
{
  "listAvailableOptions": false,
  "formName": "I-130",
  "formCategory": "134A-IR",
  "officeCode": "SCD",
  "receiptDate": "2024-03-18",
  "targets": [
    {
      "label": "Nguyen family petition",
      "formName": "I-130",
      "formCategory": "134A-IR",
      "officeCode": "SCD",
      "receiptDate": "2024-03-18"
    },
    {
      "label": "Patel naturalisation",
      "formName": "N-400",
      "formCategory": "160A",
      "officeCode": "NYC"
    }
  ],
  "monitorMode": false,
  "watchlistId": "default",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}
```

# Actor output Schema

## `dataset` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "formName": "I-130",
    "formCategory": "134A-IR",
    "officeCode": "SCD"
};

// Run the Actor and wait for it to finish
const run = await client.actor("nerolabs/uscis-processing-time-monitor").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "formName": "I-130",
    "formCategory": "134A-IR",
    "officeCode": "SCD",
}

# Run the Actor and wait for it to finish
run = client.actor("nerolabs/uscis-processing-time-monitor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "formName": "I-130",
  "formCategory": "134A-IR",
  "officeCode": "SCD"
}' |
apify call nerolabs/uscis-processing-time-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nerolabs/uscis-processing-time-monitor"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/h4nB5UCUgB6XzIbMZ/builds/xdqi4HCxmVUa7aNyQ/openapi.json
