# BLS Labor Statistics Scraper (`jobscrawler/bls-labor-statistics-scraper`) Actor

Retrieve real BLS public API v1 observations with native series/year/period/value fields, footnotes, exact value strings and retrieval provenance. No vendor API key or fabricated observations.

- **URL**: https://apify.com/jobscrawler/bls-labor-statistics-scraper.md
- **Developed by:** [Jobs Scraper](https://apify.com/jobscrawler) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.99 / 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.

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### What does BLS Labor Statistics Scraper do?

Retrieve **actual time-series observations** from the [U.S. Bureau of Labor Statistics public API v1](https://www.bls.gov/developers/api_signature.htm). This is an economic-statistics Actor, not a job-vacancy scraper. It returns the source's reported year, period, value, latest flag and available footnotes. It does not create sample observations, invent units, fill missing months, or replace a failed request with page metadata. The documented v1 routes do not need a vendor API key.

### Why use this BLS API Actor?

Use it to collect source observations for employment research, reporting, or reproducible data pipelines. A normal single-series run is one GET request. Multiple series and year ranges are batched into one POST request by default, reducing calls and respecting the source's quotas. Explicit multi-series GET mode has bounded concurrency from one to four. Apify provides scheduling, API access, integrations, storage and run monitoring; these platform services may incur charges.

### How to retrieve observations

1. Keep the example series ID, or supply your own exact official BLS series identifiers.
2. Set the global maximum observations, normally 10.
3. Optionally supply both startYear and endYear, covering at most ten years.
4. Run the Actor and inspect the actual dataset and SOURCE_METADATA.
5. Export results through Apify or retrieve them from the dataset API.

### Input and precedence

See the Input tab for all configuration options. The default series is LNS14000000, retrieved from [the actual public endpoint](https://api.bls.gov/publicAPI/v1/timeseries/data/LNS14000000). A single startUrl takes precedence over startUrls, followed by searchQuery/keyword, then seriesIds. Search query means exact uppercase BLS IDs separated by commas, not natural-language search. Geography and subject are encoded in series IDs; a free-text location filter is rejected.

Only the official HTTPS api.bls.gov v1 single-series URL pattern is accepted as a source URL. Redirects, credentials, unrelated hosts and arbitrary query parameters are not followed. The method defaults to AUTO: one unbounded series uses GET; multiple series or explicit years use POST. GET with a year range is rejected. Zero years means the API's default recent coverage, not a fabricated current-year window. A maximum of 25 distinct series is accepted.

### Output and provenance

| Field | Meaning |
|---|---|
| id | Unique source series/year/period combination |
| seriesId | Returned series ID, verified against the request |
| year, period, periodName | Actual observation period |
| reportedValue | Original reported string, preserving precision |
| value | Numeric conversion only for wholly numeric strings |
| latest | Present only when the source explicitly returns the flag |
| footnotes | Actual non-empty source notes |
| sourceUrl, fetchedAt | Actual retrieval endpoint and UTC retrieval time |
| rawData | Native observation fields without empty placeholders |

Rows are ordered by newest year and period, with requested series order breaking ties. maxItems is a global cap, not a per-series cap. M13 annual rows are excluded unless includeAnnual is true. Unknown values are omitted; real zero and false values are retained. Units and seasonal-adjustment interpretations are not guessed. A numeric value alone must not be interpreted without the series definition.

You can download the dataset in various formats such as JSON, HTML, CSV, or Excel. These two abbreviated examples show structure only; they are documentation, not real test evidence:

```json
[
  {"id":"LNS00000000:2026:M09","seriesId":"LNS00000000","year":2026,"period":"M09","periodName":"September","reportedValue":"4.2","value":4.2},
  {"id":"LNS00000000:2026:M08","seriesId":"LNS00000000","year":2026,"period":"M08","periodName":"August","reportedValue":"4.1","value":4.1}
]
```

### Limitations, costs and testing

Honor BLS request and series quotas. Rate limits and denied responses are not retried or routed through new proxies. No paid vendor API, browser, account, or private endpoint is used. A successful HTTP status is insufficient: the BLS response must report REQUEST_SUCCEEDED and return matching series identities. Source errors and zero-output runs fail; diagnostics are stored separately from observations.

Test locally with `apify run`. Local storage is not uploaded to Console, and a local pass does not prove production deployment. Source data may be revised or unavailable. Fewer than ten observations are not padded.

### Attribution, disclaimer and support

Record the retrieval date when citing observations. Under [BLS API terms](https://www.bls.gov/developers/termsOfService.htm), “BLS.gov cannot vouch for the data or analyses derived from these data after the data have been retrieved from BLS.gov.” This independent Actor is not endorsed by BLS and does not use its official logo. Report problems through the Issues tab with the series IDs, sanitized input and run ID. Never submit credentials in an issue.

# Actor input Schema

## `seriesIds` (type: `array`):

Exact series IDs. No natural-language or vacancy search is inferred.

## `searchQuery` (type: `string`):

Optional exact series ID or comma-separated IDs. Overrides seriesIds; an explicit start URL takes precedence.

## `startUrl` (type: `string`):

Optional official v1 API URL. Overrides series query and seriesIds.

## `startUrls` (type: `array`):

Optional official single-series API URLs; used only if startUrl is empty.

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

Global output cap across all returned series, newest year/period first.

## `startYear` (type: `integer`):

0 means use the API default recent period; otherwise supply both years.

## `endYear` (type: `integer`):

0 means API default. A supplied range may span at most ten years.

## `includeAnnual` (type: `boolean`):

Include native M13 annual observations; otherwise exclude them.

## `requestMethod` (type: `string`):

AUTO uses GET for one unbounded series, POST for multiple series or a year range.

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

Bounded parallel requests only when explicitly using GET for multiple series. POST batches are one request.

## `requestTimeoutSecs` (type: `integer`):

Seconds per request. Denials and rate limits are not retried.

## Actor input object example

```json
{
  "seriesIds": [
    "LNS14000000"
  ],
  "searchQuery": "LNS14000000",
  "startUrl": "https://api.bls.gov/publicAPI/v1/timeseries/data/LNS14000000",
  "startUrls": [
    {
      "url": "https://api.bls.gov/publicAPI/v1/timeseries/data/LNS14000000"
    }
  ],
  "maxItems": 10,
  "startYear": 0,
  "endYear": 0,
  "includeAnnual": false,
  "requestMethod": "AUTO",
  "maxConcurrency": 3,
  "requestTimeoutSecs": 25
}
```

# Actor output Schema

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

Dataset containing extracted public records.

## `runSummary` (type: `string`):

Run status and output counts.

## `diagnostics` (type: `string`):

Source metadata and sanitized errors.

# 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 = {
    "seriesIds": [
        "LNS14000000"
    ],
    "searchQuery": "LNS14000000",
    "startUrl": "https://api.bls.gov/publicAPI/v1/timeseries/data/LNS14000000",
    "startUrls": [
        {
            "url": "https://api.bls.gov/publicAPI/v1/timeseries/data/LNS14000000"
        }
    ],
    "maxItems": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("jobscrawler/bls-labor-statistics-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 = {
    "seriesIds": ["LNS14000000"],
    "searchQuery": "LNS14000000",
    "startUrl": "https://api.bls.gov/publicAPI/v1/timeseries/data/LNS14000000",
    "startUrls": [{ "url": "https://api.bls.gov/publicAPI/v1/timeseries/data/LNS14000000" }],
    "maxItems": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("jobscrawler/bls-labor-statistics-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 '{
  "seriesIds": [
    "LNS14000000"
  ],
  "searchQuery": "LNS14000000",
  "startUrl": "https://api.bls.gov/publicAPI/v1/timeseries/data/LNS14000000",
  "startUrls": [
    {
      "url": "https://api.bls.gov/publicAPI/v1/timeseries/data/LNS14000000"
    }
  ],
  "maxItems": 10
}' |
apify call jobscrawler/bls-labor-statistics-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,jobscrawler/bls-labor-statistics-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/2qM4NfG6tYFvUUOFe/builds/OTIvCHGnJdyvVPxmG/openapi.json
