# BLS Official Print (CPI, PPI, CES) (`oddsmith/bls-official-print`) Actor

One dataset row per BLS Public Data API v2 observation. PPE $0.002 per row.

- **URL**: https://apify.com/oddsmith/bls-official-print.md
- **Developed by:** [oddsmith Data](https://apify.com/oddsmith) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$2.00 / 1,000 bls observations

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/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

### What does BLS Official Print do?

One dataset row per observation from the **BLS Public Data API v2**. This is official print, not a scrape of bls.gov HTML. The Actor POSTs to `https://api.bls.gov/publicAPI/v2/timeseries/data/`.

### Why use it

- Drop CPI, PPI, and CES print into a scheduler or a notebook without copying tables off bls.gov.
- Keep **suppressed months** as `value: null` with `value_raw: "-"` and the bureau footnote. No fabricated numbers.
- Optionally ask BLS for **net and percent-change calculations** (`calculations: true`) and annual averages.
- Cite the series. This SKU does not forecast, nowcast, or wrap non-BLS series.

### What you get

Each dataset item is one observation. You are billed the **`row`** event once per item actually written, including suppressed `-` months (those are real BLS rows, not invented values).

| Field | Type | Notes |
| --- | --- | --- |
| `series_id` | string | BLS series identifier |
| `survey` | string | Inferred from prefix: CPI, CPI-W, C-CPI, PPI, PPI-industry, CES, ECI, CPS, LAUS, or UNKNOWN |
| `year` | string | Observation year |
| `period` | string | `M01`–`M13` or quarter codes |
| `period_name` | string | January, Annual, etc. |
| `value` | number | null | Numeric print, or `null` when BLS published `-` / `NA` |
| `value_raw` | string | Raw BLS value string |
| `latest` | boolean | True when BLS flagged the point as latest |
| `footnotes` | array | Non-empty footnote objects |
| `calculations` | object | null | BLS net/percent-change object when you set input `calculations: true` |
| `catalog_title` | string | null | Series title when catalog was returned |
| `catalog` | object | null | Full catalog object when BLS returned one |
| `retrieved_at` | string | UTC timestamp of the API call |

### How much it costs

Pay-per-event. One event, charged **only on a successful write**.

| Event name | Title | Bronze price |
| --- | --- | --- |
| `row` | BLS observation | **$0.002** |

No `row` charge on `REQUEST_FAILED`, a bad year range, or an unknown preset. Store context (Demand, 2026-08-28, retrieved): BLS/FRED/CPI listings on the Store show roughly 0–1 monthly users. This SKU is official-print plumbing, not a demand leader. It ships because CoS locked it, not because the category is crowded.

### Input

See the input tab. Required: `presets` and/or `seriesIds` (max 50 series per BLS v2 call).

Presets:

| Input | Series | Survey |
| --- | --- | --- |
| `cpi_u` | `CUUR0000SA0` | CPI-U, all items |
| `ppi_final_demand` | `WPUFD4` | PPI final demand |
| `ces_total_nonfarm` | `CES0000000001` | CES total nonfarm employment |

Other fields:

- `startYear` / `endYear` (four-digit). Unregistered calls are limited to 10 years; a registration key allows 20.
- `registrationKey` (secret, optional). Raises daily limits and unlocks catalog titles. Never stored in git. Get one at https://data.bls.gov/registrationEngine/
- `catalog` (default true). Series titles need a registration key.
- `calculations` (default **false**). When true, BLS returns net and percent-change calculations on each observation; this Actor stores that object on the row.
- `annualAverage` (default false)
- `latestOnly` (default false). Keeps the first observation BLS returns per series (API v2 is newest-first).

### Output

Download the dataset as JSON, CSV, Excel, or HTML. Example rows:

```json
{
  "series_id": "CUUR0000SA0",
  "survey": "CPI",
  "year": "2025",
  "period": "M12",
  "period_name": "December",
  "value": 324.054,
  "value_raw": "324.054",
  "latest": true,
  "footnotes": [],
  "calculations": null,
  "catalog_title": "All items in U.S. city average, all urban consumers, not seasonally adjusted",
  "catalog": { "series_title": "All items in U.S. city average, all urban consumers, not seasonally adjusted" },
  "retrieved_at": "2026-08-28T20:00:00+00:00"
}
```

A suppressed month keeps `value` null, `value_raw` `"-"`, and the footnote. You still get the row.

### Not in v1

Forecasts, nowcasts, hurricane landfall, elections, or any non-BLS series.

### Terms of use and takedown

This Actor reads the **BLS Public Data API v2** only. It does not scrape bls.gov HTML and does not invent values for suppressed months.

**ToS.** You must follow BLS terms of use and citation rules for republished series. Do not present observations as a BLS product, as a forecast, or as anything other than the bureau's published print. A registration key, if you use one, stays in Actor input and out of git.

**Takedown.** BLS public series are generally redistributable with attribution. If the bureau or a downstream licensee needs a series dropped from presets or docs, email nicholas.jaskolski@gmail.com with the subject `takedown bls-official-print` and the series ID. Confirmed requests are honored.

# Actor input Schema

## `presets` (type: `array`):

cpi\_u (CUUR0000SA0), ppi\_final\_demand (WPUFD4), ces\_total\_nonfarm (CES0000000001).

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

Raw series identifiers. Combined with presets. Max 50 per BLS v2 request.

## `startYear` (type: `string`):

Four-digit year. Unregistered calls are limited to 10 years; registered keys allow 20.

## `endYear` (type: `string`):

Four-digit year.

## `registrationKey` (type: `string`):

Optional. Raises daily query limits and unlocks catalog metadata. Get one at https://data.bls.gov/registrationEngine/. Never committed to git.

## `catalog` (type: `boolean`):

Requires a registration key for BLS to return series titles.

## `calculations` (type: `boolean`):

When true, BLS returns net and percent-change calculations on each observation.

## `annualAverage` (type: `boolean`):

When true, include BLS annual average periods.

## `latestOnly` (type: `boolean`):

Keep the first observation BLS returns per series (API v2 is newest-first).

## Actor input object example

```json
{
  "presets": [
    "cpi_u",
    "ppi_final_demand",
    "ces_total_nonfarm"
  ],
  "startYear": "2024",
  "endYear": "2025",
  "catalog": true,
  "calculations": false,
  "annualAverage": false,
  "latestOnly": false
}
```

# Actor output Schema

## `observations` (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 = {
    "presets": [
        "cpi_u",
        "ppi_final_demand",
        "ces_total_nonfarm"
    ],
    "startYear": "2024",
    "endYear": "2025"
};

// Run the Actor and wait for it to finish
const run = await client.actor("oddsmith/bls-official-print").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 = {
    "presets": [
        "cpi_u",
        "ppi_final_demand",
        "ces_total_nonfarm",
    ],
    "startYear": "2024",
    "endYear": "2025",
}

# Run the Actor and wait for it to finish
run = client.actor("oddsmith/bls-official-print").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 '{
  "presets": [
    "cpi_u",
    "ppi_final_demand",
    "ces_total_nonfarm"
  ],
  "startYear": "2024",
  "endYear": "2025"
}' |
apify call oddsmith/bls-official-print --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,oddsmith/bls-official-print"
        }
    }
}

```

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/tmWoT3QhqrfhK1qsk/builds/1xRfenvbYIN2qTThh/openapi.json
