Obscura

H-1B Approvals

Approved H-1B visa petitions by employer, from USCIS.

h1b_approvals — the dataset name to pass to the Obscura API.

Category Government Columns 12 Refresh Weekly Point-in-time available_date

What one row means

One employer's H-1B petition approval/denial counts — split into initial (new) and continuing (extension/amendment) petitions — for one worksite city/state/ZIP, for one USCIS federal fiscal year; sourced one-CSV-per- fiscal-year from the USCIS H-1B Employer Data Hub (h1b_datahubexport-{year}.csv). History back to FY2009.

One row per (fiscal_year, employer, state, city, zip).

Point-in-time availability

Every Obscura dataset carries available_date: the calendar day the publisher made the row available, day-of, with no session rounding. It is the one column a backtest filters on, and it means the same thing on every dataset in the catalog.

For h1b_approvals: published: available_date = period_end (USCIS fiscal-year-end, Sep 30 of fiscal_year) + ~183d, USCIS's documented post-FY-close Employer Data Hub dissemination lag.

Refresh cadence

Obscura refreshes h1b_approvals weekly — the most frequent scheduled job that re-collects or re-exports it. This is Obscura's own pipeline cadence, not the upstream publisher's release schedule; when a row became public is recorded per row in available_date.

Schema — 12 columns

The full public column list for h1b_approvals, with the meaning of every field. The same schema is served unauthenticated at https://api.obscura.trade/v1/catalog/h1b_approvals.

ColumnTypeDescription
fiscal_yearinteger · not nullUSCIS federal fiscal year the counts cover (Oct 1 of fiscal_year-1 through Sep 30 of fiscal_year), taken verbatim from CSV field 0 'Fiscal Year' of h1b_datahubexport-{year}.csv. Part of the composite primary key; the orchestrator task (h1b.rs) always re-fetches the newest present fiscal_year (still accruing) and skips older, already-final years.
employertext · not nullPetitioning employer's name exactly as USCIS reports it in CSV field 1 'Employer' (raw casing/punctuation preserved; commas inside quoted CSV fields kept intact by csv_util::rows). Part of the composite primary key; rows with a blank employer are dropped during parsing (parse_csv).
statetext · not nullTwo-letter US state abbreviation of the employer worksite location, from CSV field 8 'State'. Part of the composite primary key.
citytext · not nullEmployer worksite city, from CSV field 9 'City', as USCIS provides it (typically uppercase). Part of the composite primary key.
ziptext · not nullEmployer worksite 5-digit ZIP code, from CSV field 10 'ZIP'. Stored as text (not integer) because leading zeros are significant (e.g. '08854' for Piscataway, NJ) and would be lost as a number. Part of the composite primary key.
initial_approvalinteger · not nullCount of new (first-time, non-extension) H-1B petitions USCIS approved for this employer/worksite/fiscal_year, from CSV field 2 'Initial Approval'. Defaults to 0 when the CSV cell is blank/unparseable (fn int() in h1b.rs). The core hiring/expansion signal for this dataset — new headcount, as opposed to continuing_approval which is renewals of existing staff.
initial_denialinteger · not nullCount of new H-1B petitions USCIS denied for this employer/worksite/fiscal_year, from CSV field 3 'Initial Denial'. Defaults to 0 on a blank/unparseable cell.
continuing_approvalinteger · not nullCount of continuing (extension/amendment, i.e. renewing an existing H-1B worker's status) petitions USCIS approved for this employer/worksite/fiscal_year, from CSV field 4 'Continuing Approval'. Defaults to 0 on a blank/unparseable cell; distinct from initial_approval (net-new hires).
continuing_denialinteger · not nullCount of continuing H-1B petitions USCIS denied for this employer/worksite/fiscal_year, from CSV field 5 'Continuing Denial'. Defaults to 0 on a blank/unparseable cell.
naicstextTwo-digit NAICS sector code for the employer's industry (e.g. '54' Professional/Scientific/Technical Services, '51' Information), from CSV field 6 'NAICS'. Nullable: USCIS's Tax ID field (CSV field 7) is dropped entirely by the collector (never persisted, for privacy) and a blank NAICS cell is normalized to NULL rather than an empty string (h1b.rs parse_csv).
period_enddateSTORED generated column: make_date(fiscal_year, 9, 30) — the true natural close of the USCIS federal fiscal year (Oct 1 of fiscal_year-1 through Sep 30 of fiscal_year). The period/event basis available_date's lag is measured from.
available_datedateSTORED generated column: period_end (fiscal-year-end, Sep 30) + 183 days, USCIS's documented post-FY-close Employer Data Hub dissemination lag. The true public-availability date — the point-in-time column to filter/join on. Read-only.

Access h1b_approvals

Two delivery paths, one identifier. Both require an Obscura account and an active subscription; the catalog entry and the schema above are public.

import obscura

client = obscura.Client("obs_live_…")

df = client.query(
    dataset="h1b_approvals",
    start="2024-01-01",
)

Create a free account Browse all 95 datasets

Frequently asked questions

What is in the h1b_approvals dataset?

Approved H-1B visa petitions by employer, from USCIS. One employer's H-1B petition approval/denial counts — split into initial (new) and continuing (extension/amendment) petitions — for one worksite city/state/ZIP, for one USCIS federal fiscal year; sourced one-CSV-per- fiscal-year from the USCIS H-1B Employer Data Hub (h1b_datahubexport-{year}.csv). History back to FY2009.

How do I avoid look-ahead bias with h1b_approvals?

Filter on h1b_approvals.available_date, the day the publisher made the row public. For this dataset that date is derived as follows — published: available_date = period_end (USCIS fiscal-year-end, Sep 30 of fiscal_year) + ~183d, USCIS's documented post-FY-close Employer Data Hub dissemination lag. A query of the form WHERE available_date <= '<as-of date>' never sees a row before it existed.

In what formats can I get h1b_approvals?

As a Parquet bulk export (POST https://api.obscura.trade/v1/download) or as JSON from the typed query API (POST https://api.obscura.trade/v1/query), both with dataset="h1b_approvals". The column schema is public at https://api.obscura.trade/v1/catalog/h1b_approvals.

How often is h1b_approvals updated?

Obscura refreshes h1b_approvals on a weekly schedule — that is the most frequent scheduled job that re-collects or re-exports the table. It is Obscura's own pipeline cadence, not the upstream publisher's release schedule; when the publisher makes a row available is described by the availability rule above, and is recorded per row in available_date.

Related datasets

Border CrossingsMonthly inbound crossings at U.S. land ports on the Canadian and Mexican borders, split by mode (trucks, trains, persona… Congress LeaderboardWhich members of Congress have done best on the stock purchases they disclose: one dollar-weighted, one-year-forward ret… Congress TradesStock and asset trades disclosed by members of Congress and their households under the STOCK Act, parsed from House and … FEMA DisastersFederally declared disasters with type, location and dates, from FEMA. Government Contract TickersA crosswalk from federal-contract recipient names to ticker symbols, so government awards can be matched to public compa… GPR Index DailyThe daily Geopolitical Risk index of Caldara and Iacoviello, derived from newspaper coverage of geopolitical tension. GPR Index MonthlyThe monthly Geopolitical Risk index (Caldara and Iacoviello), with deeper history than the daily version. LEHD J2J FlowsJob-to-job worker flows from the Census LEHD program: how workers move between employers, industries and regions.