# H-1B LCA Disclosure Data Scraper (`crawlerbros/h1b-lca-disclosure-scraper`) Actor

Scrape US Department of Labor (DOL) H-1B / H-1B1 / E-3 Labor Condition Application (LCA) disclosure data. Search by employer, job title, SOC code, wage, worksite state, visa class, and more, or look up exact case numbers.

- **URL**: https://apify.com/crawlerbros/h1b-lca-disclosure-scraper.md
- **Developed by:** [Crawler Bros](https://apify.com/crawlerbros) (community)
- **Categories:** Jobs, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## H-1B LCA Disclosure Data Scraper

Scrape **US Department of Labor (DOL) H-1B / H-1B1 / E-3 Labor Condition Application (LCA) disclosure data** — the official quarterly dataset every employer sponsoring an H-1B, H-1B1, or E-3 visa worker must file. Search by employer, job title, SOC occupation code, wage range, worksite state/city, visa class, and more, or look up exact case numbers. No auth or cookies required; a Residential proxy is required since dol.gov blocks datacenter egress IPs on these large downloads.

### What this actor does

- **Two modes:** `search` (filter across the full disclosure file) and `byCaseNumbers` (exact lookup)
- **Selectable fiscal year:** scan the latest quarterly file (auto-discovered) or any closed fiscal year back to FY2020
- **Rich filters:** employer name, employer FEIN (exact), job title, SOC occupation title/code, NAICS code, case status, visa class, worksite state/city, employer (sponsor) state, wage range and pay unit, prevailing wage range/level, total worker positions range, full-time only, filed with an agent/attorney, attorney/law firm name, H-1B dependent employer, willful violator, received/decision date ranges
- **Full case detail:** employer, worksite, wage, attorney/agent, and preparer information per record
- **Multi-worksite detail:** the small share of cases that disclose more than one physical worksite get every location joined in automatically from DOL's separate LCA Worksites file
- **Empty fields are omitted**

### Output per LCA disclosure

- `caseNumber`, `caseStatus`, `visaClass`
- `receivedDate`, `decisionDate`, `originalCertDate`, `beginDate`, `endDate`
- `jobTitle`, `socCode`, `socTitle`, `fullTimePosition`
- `totalWorkerPositions`, `newEmploymentCount`, `continuedEmploymentCount`, `changePreviousEmploymentCount`, `newConcurrentEmploymentCount`, `changeEmployerCount`, `amendedPetitionCount`
- `employerName`, `tradeNameDba`, `employerAddress`, `employerCity`, `employerState`, `employerPostalCode`, `employerCountry`, `employerProvince`, `employerPhone`, `employerFein`, `naicsCode`
- `employerPocName`, `employerPocJobTitle`, `employerPocAddress`, `employerPocCity`, `employerPocState`, `employerPocPostalCode`, `employerPocCountry`, `employerPocProvince`, `employerPocPhone`, `employerPocEmail`
- `agentRepresentingEmployer`, `agentAttorneyName`, `agentAttorneyAddress`, `agentAttorneyCity`, `agentAttorneyState`, `agentAttorneyPostalCode`, `agentAttorneyCountry`, `agentAttorneyProvince`, `agentAttorneyPhone`, `agentAttorneyEmail`, `lawfirmName`, `lawfirmFein`, `attorneyBarState`, `attorneyBarCourt`
- `worksiteWorkers`, `secondaryEntity`, `secondaryEntityBusinessName`, `worksiteAddress`, `worksiteCity`, `worksiteCounty`, `worksiteState`, `worksitePostalCode`
- `wageRateFrom`, `wageRateTo`, `wageUnitOfPay`, `prevailingWage`, `pwUnitOfPay`, `pwTrackingNumber`, `pwWageLevel`, `pwOesYear`, `pwOtherSource`, `pwOtherYear`, `pwSurveyPublisher`, `pwSurveyName`
- `totalWorksiteLocations`, `agreeToLcStatement`, `h1bDependent`, `willfulViolator`, `supportH1b`, `statutoryBasis`, `appendixAAttached`, `publicDisclosure`
- `masterExemptionWorkerCount`, `masterExemptionDegrees` (array of `{institutionName, fieldOfStudy, dateOfDegree}`) — advanced-degree exemption detail from DOL's Appendix A file, present only for the subset of H-1B-dependent-employer cases that claim the masters/advanced-degree exemption
- `additionalWorksiteLocations` (array of `{worksiteWorkers, secondaryEntity, secondaryEntityBusinessName, worksiteAddress, worksiteCity, worksiteCounty, worksiteState, worksitePostalCode, wageRateFrom, wageRateTo, wageUnitOfPay, prevailingWage, pwUnitOfPay, pwWageLevel}`) — every worksite location DOL's separate LCA Worksites file discloses for the case, joined in by case number automatically; present only for the minority of cases that report more than one worksite (a filing can disclose up to 10)
- `preparerName`, `preparerBusinessName`, `preparerEmail`
- `sourceUrl` — the DOL disclosure file this record came from
- `recordType: "lcaDisclosure"`, `scrapedAt`

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | string | `search` | `search` / `byCaseNumbers` |
| `fiscalYear` | string | `latest` | `latest` (auto-discovered) / `FY2025` / `FY2024` / `FY2023` / `FY2022` / `FY2021` / `FY2020` |
| `caseNumbers` | array | – | Exact case numbers to look up (mode=byCaseNumbers) |
| `employerName` | string | – | Substring match on employer legal name or trade name/DBA |
| `jobTitle` | string | – | Substring match on job title |
| `socCode` | string | – | Exact or prefix match on SOC code, e.g. `19-2031` |
| `caseStatus` | string | any | `Certified` / `Certified - Withdrawn` / `Denied` / `Withdrawn` |
| `visaClass` | string | any | `H-1B` / `H-1B1 Chile` / `H-1B1 Singapore` / `E-3 Australian` |
| `worksiteState` | string | any | Two-letter US state/territory code |
| `worksiteCity` | string | – | Substring match on worksite city |
| `naicsCode` | string | – | Exact or prefix match on employer NAICS code |
| `socTitle` | string | – | Substring match on the SOC occupation category name (e.g. `Software Developers`), distinct from `jobTitle` |
| `lawfirmOrAttorneyName` | string | – | Substring match on the filing attorney's name or the law firm/business name |
| `employerFein` | string | – | Exact match on the sponsoring employer's FEIN (dashes/spaces ignored) |
| `fullTimePositionOnly` | boolean | `false` | Only emit full-time positions |
| `totalWorkerPositionsMin` / `totalWorkerPositionsMax` | int | – | Range on total worker positions requested on the LCA |
| `wageMin` / `wageMax` | int | – | Range on offered wage (`wageRateFrom`) |
| `prevailingWageMin` / `prevailingWageMax` | int | – | Range on prevailing wage |
| `pwWageLevel` | string | any | `I` / `II` / `III` / `IV` |
| `wageUnitOfPay` | string | any | Offered-wage pay period: `Year` / `Hour` / `Week` / `Bi-Weekly` / `Month` |
| `employerState` | string | any | Two-letter US state/territory code of the sponsoring employer's own address (distinct from worksite state) |
| `hasAgentOrAttorney` | string | any | `yes` (filed via an agent/attorney) / `no` (self-filed) |
| `h1bDependentOnly` | boolean | `false` | Only H-1B dependent employers |
| `willfulViolatorOnly` | boolean | `false` | Only listed willful violators |
| `receivedDateFrom` / `receivedDateTo` | string | – | ISO date `YYYY-MM-DD` range on received date |
| `decisionDateFrom` / `decisionDateTo` | string | – | ISO date `YYYY-MM-DD` range on decision date |
| `employmentBeginDateFrom` / `employmentBeginDateTo` | string | – | ISO date `YYYY-MM-DD` range on the requested employment start date |
| `employmentEndDateFrom` / `employmentEndDateTo` | string | – | ISO date `YYYY-MM-DD` range on the requested employment end date |
| `maxItems` | int | `50` | Hard cap (1–5000). A very high value combined with a restrictive filter may take several minutes since the whole quarterly file must be scanned once. |
| `proxyConfiguration` | object | Residential | Required. dol.gov blocks Apify's own IPs and the default datacenter proxy pool on these large downloads; a Residential proxy group is needed to reliably fetch the file. |

#### Example: search by employer and worksite state

```json
{
  "mode": "search",
  "employerName": "Google",
  "worksiteState": "CA",
  "visaClass": "H-1B",
  "maxItems": 100
}
```

#### Example: high-wage software engineering roles

```json
{
  "mode": "search",
  "jobTitle": "software engineer",
  "wageMin": 150000,
  "fullTimePositionOnly": true,
  "maxItems": 200
}
```

#### Example: lookup exact case numbers

```json
{
  "mode": "byCaseNumbers",
  "caseNumbers": ["I-200-25181-143022", "I-200-26083-726723"]
}
```

#### Example: a prior fiscal year, denied cases only

```json
{
  "mode": "search",
  "fiscalYear": "FY2024",
  "caseStatus": "Denied",
  "maxItems": 500
}
```

### Use cases

- **Immigration law firms** — research an employer's H-1B sponsorship history and prevailing wage levels before filing
- **Compensation benchmarking** — pull real offered/prevailing wages by SOC code, state, or employer to benchmark salary bands
- **Journalism & policy research** — analyze H-1B dependent employers, denial rates, or willful violator listings
- **Recruiting & talent sourcing** — identify which employers actively sponsor visas for a given job title or occupation
- **Compliance monitoring** — track your own or a competitor's LCA filings, case statuses, and worksite locations
- **Academic research** — bulk-export a fiscal year's disclosure data for labor-market analysis

### FAQ

**What is an LCA?** A Labor Condition Application is a form employers file with the US Department of Labor before petitioning for an H-1B, H-1B1 (Chile/Singapore), or E-3 (Australia) visa worker. It attests to wage and working-condition commitments.

**Where does this data come from?** The US DOL Office of Foreign Labor Certification (OFLC) publishes cumulative quarterly disclosure files publicly at dol.gov. This actor is not affiliated with the US Department of Labor — it's a third-party tool built on that public dataset.

**How often is the data updated?** DOL publishes a new quarterly file roughly 4-6 weeks after each fiscal quarter closes. Fiscal Year runs October–September. Use `fiscalYear: "latest"` to always get the newest available file.

**Why do older fiscal years only offer one option instead of per-quarter files?** Once a fiscal year is closed, DOL's Q4 cumulative file already contains that entire year's records, so a single selection covers it.

**What's the difference between `wageRateFrom`/`wageRateTo` and `prevailingWage`?** `wageRateFrom`/`wageRateTo` is the wage the employer is offering the worker (a range if applicable). `prevailingWage` is the DOL-determined minimum wage for that occupation/location/experience level that the employer must meet or exceed.

**What does `h1bDependent` mean?** An employer is "H-1B dependent" if it meets DOL's headcount-ratio threshold for H-1B workers, which triggers additional attestation requirements. This field is omitted when the source marks it not-applicable (e.g., non-H-1B visa classes).

**Why are some records missing attorney/agent fields?** Not every employer uses an attorney or agent to file; those fields are simply omitted when the employer self-filed.

**What are `masterExemptionWorkerCount` / `masterExemptionDegrees`?** H-1B-dependent employers can exempt a worker from extra attestation requirements if that worker holds a US master's degree or higher (or foreign equivalent). DOL's separate "Appendix A" file records the exempt worker's institution, field of study, and degree date for cases that claim this exemption; this actor joins it in by case number automatically (no extra input needed). These fields are omitted for the (large majority of) cases that don't claim the exemption.

**What is `additionalWorksiteLocations`?** DOL lets an employer disclose up to 10 physical worksite locations per LCA in a separate "LCA Worksites" file. Most cases have just one (already reflected in the top-level `worksiteAddress`/`worksiteCity`/etc. fields), so this array is only added for the minority of cases with more than one disclosed location — giving you every location DOL published for that case, not just the primary one. Omitted entirely for single-location cases.

**Can I get every record in a fiscal year?** Yes — set `maxItems` up to 5000 with broad/no filters. The full file has 600K-900K rows; a very restrictive filter combined with a very high `maxItems` can take several minutes because the whole file is streamed once per run.

**Is this actor US-only?** Yes — the DOL LCA program covers US employment only, so `worksiteState` and `employerState` are always US states/territories.

# Actor input Schema

## `mode` (type: `string`):

What to fetch.

## `fiscalYear` (type: `string`):

Which DOL disclosure file to scan. `latest` auto-discovers the newest quarterly file for the current fiscal year (currently FY2026 Q2). Older fiscal years are closed/final (through Q4).

## `caseNumbers` (type: `array`):

Exact LCA case numbers to look up, e.g. `I-200-25181-143022`.

## `employerName` (type: `string`):

Case-insensitive substring match against employer legal name OR trade name / DBA.

## `jobTitle` (type: `string`):

Case-insensitive substring match against the job title.

## `socCode` (type: `string`):

Exact match or prefix match against the Standard Occupational Classification code, e.g. `19-2031` or `19-2031.00`.

## `caseStatus` (type: `string`):

Filter to a specific case status.

## `visaClass` (type: `string`):

Filter to a specific visa classification.

## `worksiteState` (type: `string`):

Filter to a specific US worksite state/territory.

## `worksiteCity` (type: `string`):

Case-insensitive substring match against the worksite city.

## `naicsCode` (type: `string`):

Exact match or prefix match against the employer's NAICS industry code, e.g. `611310` or `6113`.

## `socTitle` (type: `string`):

Case-insensitive substring match against the SOC occupation category name (e.g. `Software Developers`), distinct from `jobTitle`. Useful when you don't know the exact SOC code.

## `lawfirmOrAttorneyName` (type: `string`):

Case-insensitive substring match against the filing attorney's name OR the law firm/business name that represented the employer.

## `employerFein` (type: `string`):

Exact match on the sponsoring employer's Federal Employer Identification Number (dashes/spaces ignored), e.g. `12-3456789`. Use this instead of employer name when you need to pin down one legal entity precisely.

## `fullTimePositionOnly` (type: `boolean`):

Only emit full-time positions.

## `totalWorkerPositionsMin` (type: `integer`):

Drop records where the total number of worker positions requested on the LCA is below this value. Useful for finding bulk/high-volume filings.

## `totalWorkerPositionsMax` (type: `integer`):

Drop records where the total number of worker positions requested on the LCA is above this value.

## `wageMin` (type: `integer`):

Drop records with `wageRateFrom` below this value (in the wage's own unit of pay).

## `wageMax` (type: `integer`):

Drop records with `wageRateFrom` above this value (in the wage's own unit of pay).

## `prevailingWageMin` (type: `integer`):

Drop records with `prevailingWage` below this value.

## `prevailingWageMax` (type: `integer`):

Drop records with `prevailingWage` above this value.

## `pwWageLevel` (type: `string`):

Filter to a specific DOL prevailing wage level.

## `wageUnitOfPay` (type: `string`):

Filter to a specific offered-wage pay period.

## `employerState` (type: `string`):

Filter to a specific US state/territory of the sponsoring employer's own address (distinct from the worksite state).

## `hasAgentOrAttorney` (type: `string`):

Filter by whether an agent or attorney represented the employer on the filing.

## `h1bDependentOnly` (type: `boolean`):

Only emit records where the employer is classified as H-1B dependent.

## `willfulViolatorOnly` (type: `boolean`):

Only emit records where the employer is listed as a willful violator.

## `receivedDateFrom` (type: `string`):

ISO date `YYYY-MM-DD`. Drop records received before this date.

## `receivedDateTo` (type: `string`):

ISO date `YYYY-MM-DD`. Drop records received after this date.

## `decisionDateFrom` (type: `string`):

ISO date `YYYY-MM-DD`. Drop records decided before this date.

## `decisionDateTo` (type: `string`):

ISO date `YYYY-MM-DD`. Drop records decided after this date.

## `employmentBeginDateFrom` (type: `string`):

ISO date `YYYY-MM-DD`. Drop records whose requested employment period starts before this date.

## `employmentBeginDateTo` (type: `string`):

ISO date `YYYY-MM-DD`. Drop records whose requested employment period starts after this date.

## `employmentEndDateFrom` (type: `string`):

ISO date `YYYY-MM-DD`. Drop records whose requested employment period ends before this date.

## `employmentEndDateTo` (type: `string`):

ISO date `YYYY-MM-DD`. Drop records whose requested employment period ends after this date.

## `maxItems` (type: `integer`):

Hard cap on emitted records. The DOL disclosure file has 600K-900K rows; a very high value combined with a restrictive filter may take several minutes since the whole file must be streamed once.

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

Required. dol.gov's Akamai edge blocks Apify's own egress IPs and the default Apify datacenter proxy pool with a 403 on the large XLSX disclosure files. The actor always tries a direct connection first (fast to fail) and falls back to this proxy — it must be a Residential group for the download to succeed reliably from Apify's cloud infrastructure.

## Actor input object example

```json
{
  "mode": "search",
  "fiscalYear": "latest",
  "caseNumbers": [],
  "caseStatus": "",
  "visaClass": "",
  "worksiteState": "",
  "fullTimePositionOnly": false,
  "pwWageLevel": "",
  "wageUnitOfPay": "",
  "employerState": "",
  "hasAgentOrAttorney": "",
  "h1bDependentOnly": false,
  "willfulViolatorOnly": false,
  "maxItems": 50,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `disclosures` (type: `string`):

Dataset containing all scraped LCA disclosure records.

# 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 = {
    "mode": "search",
    "fiscalYear": "latest",
    "caseNumbers": [],
    "caseStatus": "",
    "visaClass": "",
    "worksiteState": "",
    "fullTimePositionOnly": false,
    "pwWageLevel": "",
    "wageUnitOfPay": "",
    "employerState": "",
    "hasAgentOrAttorney": "",
    "h1bDependentOnly": false,
    "willfulViolatorOnly": false,
    "maxItems": 50,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawlerbros/h1b-lca-disclosure-scraper").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 = {
    "mode": "search",
    "fiscalYear": "latest",
    "caseNumbers": [],
    "caseStatus": "",
    "visaClass": "",
    "worksiteState": "",
    "fullTimePositionOnly": False,
    "pwWageLevel": "",
    "wageUnitOfPay": "",
    "employerState": "",
    "hasAgentOrAttorney": "",
    "h1bDependentOnly": False,
    "willfulViolatorOnly": False,
    "maxItems": 50,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("crawlerbros/h1b-lca-disclosure-scraper").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 '{
  "mode": "search",
  "fiscalYear": "latest",
  "caseNumbers": [],
  "caseStatus": "",
  "visaClass": "",
  "worksiteState": "",
  "fullTimePositionOnly": false,
  "pwWageLevel": "",
  "wageUnitOfPay": "",
  "employerState": "",
  "hasAgentOrAttorney": "",
  "h1bDependentOnly": false,
  "willfulViolatorOnly": false,
  "maxItems": 50,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call crawlerbros/h1b-lca-disclosure-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,crawlerbros/h1b-lca-disclosure-scraper"
        }
    }
}

```

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/gsgUbSW72QUWNv6l0/builds/3CIhkX2GN7LivKs6a/openapi.json
