# H1B Visa Sponsor & Salary Database Scraper (`zucchini_gopher_m2v/h1bdata-scraper`) Actor

Search the US Department of Labor's public H1B LCA filing history by employer, job title, city, or year -- salary, worksite, and (optionally) full case detail including sponsoring attorney and employer contact. No account or API key needed.

- **URL**: https://apify.com/zucchini\_gopher\_m2v/h1bdata-scraper.md
- **Developed by:** [Faisal Ahdan naufal](https://apify.com/zucchini_gopher_m2v) (community)
- **Categories:** Lead generation
- **Stats:** 1 total users, 0 monthly users, 60.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.50 / 1,000 h-1b records

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

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#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

## H1B Visa Sponsor & Salary Database Scraper

Search the US Department of Labor's public H-1B sponsorship filing history by employer, job title, city, or year — real filed salaries, and (optionally) the full case record including sponsoring attorney and employer contact details. No account, login, or API key needed.

### Why use this actor

- Look up exactly what any US employer pays H-1B sponsored workers, by job title and location, sourced from official government filings
- Optional enrichment fetches the full case record per result: prevailing wage, wage level, worksite address, the employer's own point-of-contact name and email, and the sponsoring immigration attorney/law firm name and email — useful for recruiting, immigration research, or B2B outreach
- `caseDetail` mode looks up specific filings directly if you already have a case number
- No account, login, or API key required
- Stable JSON output, ready for spreadsheets, databases, or pipelines

### How it works

Pick a `mode`:

1. **`search`** — query filings by employer name, job title, worksite city, and/or fiscal year.
2. **`caseDetail`** — fetch the full record for specific case number(s) you already have.

### Input

**Search, lightweight (one row per filing):**

```json
{
  "mode": "search",
  "employer": "Google",
  "jobTitle": "",
  "city": "",
  "year": "2024",
  "maxResults": 200,
  "fetchCaseDetails": false
}
```

**Search, enriched with full case detail (wage, worksite, contacts):**

```json
{
  "mode": "search",
  "employer": "Google",
  "jobTitle": "",
  "city": "",
  "year": "2024",
  "maxResults": 50,
  "fetchCaseDetails": true
}
```

**Case detail, by case number:**

```json
{
  "mode": "caseDetail",
  "caseIds": ["I-200-21027-037298"]
}
```

| Field | Type | Description |
|---|---|---|
| `mode` | string | `"search"` (default) or `"caseDetail"`. |
| `employer` | string | `search` mode — partial or full sponsor company name, e.g. `"Google"`. Case-insensitive substring match. |
| `jobTitle` | string | `search` mode — partial or full filed job title. Filed titles are sometimes lightly mangled by the source dataset — a short, common word works best. |
| `city` | string | `search` mode — worksite city. |
| `year` | string | `search` mode — a specific fiscal year (`"2012"`–`"2025"`) or `"All Years"`. Default `"All Years"`. At least one of `employer` / `jobTitle` / `city` is required. |
| `maxResults` | integer | `search` mode — max filings to return. Default 200. |
| `fetchCaseDetails` | boolean | `search` mode — when `true`, each result is additionally fetched for its full case record. When `false` (default), only the summary row is returned — much faster for large result sets. |
| `caseIds` | array | `caseDetail` mode — case numbers to look up directly, e.g. `"I-200-21027-037298"` (found in a search result's `caseId` field). |
| `maxConcurrency` | integer | How many case-detail records to fetch in parallel. Default 4. |
| `proxyConfiguration` | object | Apify Proxy settings. Residential is on by default. |

### Output

**Search mode, `fetchCaseDetails: false`** — one lightweight record per filing (real captured output):

```json
{
  "_input": "em=Google|job=|city=|year=2024",
  "_source": "S1-search-summary",
  "_scrapedAt": "2026-08-30T17:44:17Z",
  "EMPLOYER": "GOOGLE LLC",
  "JOB_TITLE": "ACCESSIBILITY ANALYST",
  "BASE_SALARY": "105,000",
  "LOCATION": "MOUNTAIN VIEW, CA",
  "SUBMIT_DATE": "01/08/2024",
  "START_DATE": "01/25/2024",
  "caseId": "I-200-24008-624300",
  "caseUrl": "https://h1bdata.info/details.php?id=I-200-24008-624300"
}
```

**Search mode with `fetchCaseDetails: true`, or `caseDetail` mode** — full case record (real captured output, truncated):

```json
{
  "_input": "I-200-21027-037298",
  "_source": "S1-detail",
  "_scrapedAt": "2026-08-30T17:43:35Z",
  "LCA_CASE_NUMBER": "I-200-21027-037298",
  "STATUS": "Certified - Withdrawn",
  "LCA_CASE_SUBMIT": "2021-01-27",
  "DECISION_DATE": "2021-03-09",
  "VISA_CLASS": "H-1B",
  "LCA_CASE_JOB_TITLE": "SoftwareEngineer 1615.47781",
  "SOC_TITLE": "Software Developers, Applications",
  "FULL_TIME_POSITION": "True",
  "LCA_CASE_EMPLOYMENT_START_DATE": "2021-07-22",
  "END_DATE": "2024-07-21",
  "LCA_CASE_EMPLOYER_NAME": "Google LLC",
  "EMPLOYER_ADDRESS1": "1600 Amphitheatre Parkway",
  "EMPLOYER_CITY": "Mountain View",
  "EMPLOYER_STATE": "CA",
  "EMPLOYER_POC_EMAIL": "GITAMER@google.com",
  "AGENT_ATTORNEY_FIRST_NAME": "Soo",
  "AGENT_ATTORNEY_LAST_NAME": "Choi",
  "AGENT_ATTORNEY_EMAIL_ADDRESS": "GoogleDOL@balglobal.com",
  "LAWFIRM_NAME_BUSINESS_NAME": "Berry Appleman & Leiden LLP",
  "LCA_CASE_WAGE_RATE_FROM": "129000",
  "LCA_CASE_WAGE_RATE_UNIT": "Year",
  "PREVAILING_WAGE": "120578",
  "PW_WAGE_LEVEL": "II"
  ,"... 40 more fields": "worksite address, additional employer point-of-contact/attorney details, willful-violator flag, etc."
}
```

A record with `_error` instead of data means that lookup couldn't
complete — `"_error": "no_results"` (nothing matched the search),
`"_error": "case_not_found"` (invalid case number in `caseDetail` mode).
A record with `"_warning": "case_detail_unavailable"` in enriched search
mode means the summary row is real but its detail-page enrichment failed
for that one row specifically — the run still continues.

### Notes / limits

- Filed job titles come from the government dataset as-is and are
  sometimes auto-generated or lightly mangled — search with a short,
  common word rather than an exact long phrase for the best match rate.
- A very broad query (a large employer across `"All Years"`) can return
  tens of thousands of filings; `maxResults` caps the output, but for
  large employers we recommend picking a specific `year` for faster runs.
- Attorney and employer point-of-contact fields are only present on
  filings that actually used a representing attorney / listed a contact —
  they're simply absent from records where the filing didn't include one.

# Actor input Schema

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

"search" queries the H1B LCA filing database by employer / job title / city / year. "caseDetail" fetches the full case record (wage, worksite, attorney, employer contact) for specific case ID(s) directly.

## `employer` (type: `string`):

"search" mode -- partial or full sponsor company name, e.g. "Google" or "Tata Consultancy". Case-insensitive substring match. At least one of employer / jobTitle / city is required.

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

"search" mode -- partial or full job title as filed on the LCA, e.g. "Data Scientist". Note: filed job titles are often auto-generated and lightly mangled (spaces stripped, an internal code appended) -- a short, common substring works best.

## `city` (type: `string`):

"search" mode -- worksite city, e.g. "Mountain View".

## `year` (type: `string`):

"search" mode -- LCA fiscal year to search, or "All Years" for the full 2012-present history (returns more rows, slower for large employers).

## `maxResults` (type: `integer`):

"search" mode -- maximum number of filing rows to return. h1bdata.info renders every matching row on one page (no pagination) -- large employers across "All Years" can match tens of thousands of rows, so this caps both the output size and (indirectly) how much HTML gets parsed.

## `fetchCaseDetails` (type: `boolean`):

"search" mode -- when true, each matched filing is additionally fetched for its full case record (prevailing wage, wage level, worksite address, employer point-of-contact name/email, sponsoring attorney/law-firm name/email). When false (default), only the lightweight search-result row (employer, job title, base salary, location, submit/start date) is returned -- much faster for large result sets.

## `caseIds` (type: `array`):

"caseDetail" mode -- LCA case numbers to fetch full detail for directly, e.g. "I-200-21027-037298" (the case ID shown in the Base Salary column link of search results, or in a previous run's "caseId" field).

## `maxConcurrency` (type: `integer`):

How many case-detail pages to fetch in parallel ("search" mode's enrichment pass, or "caseDetail" mode's case ID list).

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

Apify Proxy configuration. Residential is on by default.

## Actor input object example

```json
{
  "mode": "search",
  "employer": "Google",
  "year": "2024",
  "maxResults": 200,
  "fetchCaseDetails": false,
  "caseIds": [
    "I-200-21027-037298"
  ],
  "maxConcurrency": 4,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `results` (type: `string`):

All scraped filing / case-detail records produced by this run.

# 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",
    "employer": "Google",
    "jobTitle": "",
    "city": "",
    "year": "2024",
    "maxResults": 200,
    "fetchCaseDetails": false,
    "caseIds": [
        "I-200-21027-037298"
    ],
    "maxConcurrency": 4,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("zucchini_gopher_m2v/h1bdata-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",
    "employer": "Google",
    "jobTitle": "",
    "city": "",
    "year": "2024",
    "maxResults": 200,
    "fetchCaseDetails": False,
    "caseIds": ["I-200-21027-037298"],
    "maxConcurrency": 4,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("zucchini_gopher_m2v/h1bdata-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",
  "employer": "Google",
  "jobTitle": "",
  "city": "",
  "year": "2024",
  "maxResults": 200,
  "fetchCaseDetails": false,
  "caseIds": [
    "I-200-21027-037298"
  ],
  "maxConcurrency": 4,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call zucchini_gopher_m2v/h1bdata-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,zucchini_gopher_m2v/h1bdata-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/EDHE4WleayRxO1ZzD/builds/wrTuFQYU5awlZ49Bl/openapi.json
