# Economic Calendar Scraper (`romajure/economic-calendar`) Actor

Economic calendar scraper for Forex Factory and Investing.com: NFP, CPI, rate decisions, PMIs with UTC time, impact, actual, forecast, previous. Pay per event.

- **URL**: https://apify.com/romajure/economic-calendar.md
- **Developed by:** [Romas Jurevicius](https://apify.com/romajure) (community)
- **Categories:** News, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 event scrapeds

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?

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

### Economic Calendar Scraper

Economic Calendar turns the public macro calendars that traders watch every day into one clean, machine-readable feed. It returns one JSON record per scheduled event - Non-Farm Payrolls, CPI, central bank rate decisions, PMIs, GDP, retail sales, speeches, bank holidays - with the release time in **UTC and ISO 8601**, the country and currency, the expected market impact (`high`, `medium`, `low`, `holiday`), and the **actual, forecast, previous and revised** figures both as the source shows them (`"3.2%"`, `"-68.3K"`) and as parsed numbers with a unit (`3.2`, `"%"`). No account, API key or login is needed on either source.

Typical uses: feeding an AI trading agent or risk engine that must know when the next high-impact release lands, building "no trading 30 minutes around NFP" guards, backfilling a research dataset with actual-vs-forecast surprises, alerting a Telegram or Slack channel before red-folder events, or powering a calendar widget without maintaining your own scrapers.

Two sources are supported and can be combined in one run:

- **`forexfactory`** (stable) - the Forex Factory calendar page for any date window, with actuals, revisions, better/worse markers and optional per-event detail (source, measures, usual effect, frequency).
- **`investing`** (experimental) - the Investing.com calendar API covering 100+ countries, with numeric values, precision, units, preliminary flags, reference periods and exchange holidays.

### How to scrape an economic calendar

1. Open the Actor in Apify Console and click **Try for free**.
2. Pick the **Sources** (default: Forex Factory) and, optionally, a **Date from** / **Date to** window. The default is today to seven days ahead.
3. Narrow the output with **Currencies** (for example `USD`, `EUR`, `GBP`) and **Impact** (for example only `high`). Filtering happens before anything is charged, so a high-impact-only run costs only the high-impact events.
4. Turn on **Include details** if you want the event description and specs next to each record.
5. Click **Start**. Results appear in the **Output** tab within seconds and can be downloaded as JSON, CSV or Excel, or read through the API.

#### How the fetching works

For Forex Factory the Actor loads the calendar for the requested window in a single request per 62 days (the page's maximum range), pinned to US Eastern time so the time labels are deterministic. The page embeds every event with a Unix timestamp, which is what `datetimeUtc` is built from - the label shown on the page is never parsed for the time. If the page is unreachable (for example a Cloudflare challenge from a bad proxy IP), the Actor falls back to Forex Factory's public weekly JSON feed, which covers only the current Sunday-to-Saturday week and carries no actual values; the run then logs a warning and clamps the window.

For Investing.com the Actor calls the same JSON API the website uses (`endpoints.investing.com/.../calendars/economic/events/occurrences`), pages through it with cursors in blocks of 200, then adds exchange holidays from the holidays endpoint, de-duplicated per country and day.

Requests are serialized with a one-second gap and retried on network errors, 429 and 5xx responses. All events are pushed in time order, and an event id is remembered in the run state so a migrated or resurrected run never charges the same event twice.

### Economic Calendar Scraper pricing

This Actor uses Apify's **pay-per-event** model. There is no subscription and no per-result platform fee on top:

- **Actor start**: a flat fee of $0.00005 per run.
- **Calendar event scraped**: **$0.002 per event** pushed to your dataset (that is $2 per 1,000 events).

Filtering by currency and impact is free and happens before charging - a week of only high-impact USD events is typically 5-15 events, so well under $0.05. Status records for a source that was unavailable or returned nothing are free. You can cap spending with **Maximum cost per run**; when the cap is reached the Actor stops cleanly and keeps everything scraped so far.

### Input example

```json
{
    "sources": ["forexfactory"],
    "dateFrom": "2026-10-12",
    "dateTo": "2026-10-18",
    "currencies": ["USD", "EUR"],
    "impact": ["high", "medium"],
    "includeDetails": false,
    "proxyConfiguration": { "useApifyProxy": true }
}
```

#### Input fields

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `sources` | array of `forexfactory` / `investing` | `["forexfactory"]` | Which calendars to read. Both can be combined; each event carries its `source`. |
| `dateFrom` | ISO date `YYYY-MM-DD` | today (UTC) | First calendar day to include. |
| `dateTo` | ISO date `YYYY-MM-DD` | `dateFrom` + 7 days | Last day to include (inclusive). Up to 367 days per run. |
| `currencies` | array of strings | none | Keep only these ISO currency codes. Use `ALL` to keep Forex Factory's worldwide events (OPEC, G20, IMF). |
| `impact` | array of `high` / `medium` / `low` / `holiday` | none | Keep only these impact levels. |
| `includeDetails` | boolean | `false` | Add a `detail` object with description and specs (one extra page per event type on Forex Factory; free on Investing.com). |
| `proxyConfiguration` | object | Apify Proxy | Standard Apify proxy settings. |

### Output example

One dataset item per event:

```json
{
    "source": "forexfactory",
    "eventId": "7d1d9fa5f1a4e5c2",
    "sourceEventId": "150997",
    "title": "Employment Change",
    "country": "Canada",
    "countryCode": "CA",
    "currency": "CAD",
    "datetimeUtc": "2026-10-09T12:30:00.000Z",
    "date": "2026-10-09",
    "timeLocalLabel": "8:30am",
    "sourceTimezone": "America/New_York",
    "impact": "high",
    "actual": "-68.3K",
    "forecast": "6.1K",
    "previous": "-41.7K",
    "revised": null,
    "actualValue": -68.3,
    "forecastValue": 6.1,
    "previousValue": -41.7,
    "revisedValue": null,
    "unit": "K",
    "actualVsForecast": "worse",
    "revisedVsPrevious": null,
    "isTentative": false,
    "isAllDay": false,
    "isPreliminary": false,
    "referencePeriod": null,
    "detail": {
        "description": "Job creation is an important leading indicator of consumer spending...",
        "specs": {
            "source": "Statistics Canada (latest release)",
            "sourceUrl": "https://www.statcan.gc.ca/",
            "measures": "Change in the number of employed people during the previous month",
            "usualEffect": "'Actual' greater than 'Forecast' is good for currency",
            "frequency": "Released monthly, usually on the first Friday after the month ends",
            "eventType": "Employment"
        },
        "detailUrl": "https://www.forexfactory.com/calendar/60-ca-employment-change"
    },
    "sourceUrl": "https://www.forexfactory.com/calendar?day=oct9.2026#detail=150997",
    "scrapedAt": "2026-10-10T20:08:22.675Z"
}
```

Field notes:

- `eventId` is a stable SHA-1 prefix of source + date + currency + title + UTC time (`HH:MM`), so the same release hashes to the same id on every run and two speeches by the same person on one day stay distinct. `sourceEventId` is the source's own id.
- `datetimeUtc` is the release instant. `date` and `timeLocalLabel` are what the source displays, in `sourceTimezone` (`America/New_York` for Forex Factory, `UTC` for Investing.com). For all-day and tentative events `datetimeUtc` is the source's placeholder time.
- `previous` is the prior print as originally published; `revised` is the revised prior print when the source shows a revision, otherwise `null`. The "effective previous" is `revised ?? previous`. `revisedVsPrevious` tells you which way it was revised.
- Numeric fields keep the unit's scale: `"1.25M"` becomes `actualValue: 1.25, unit: "M"`. Strings that are not numbers (`"Unch"`, a rate range) keep `value: null` and the raw text in `unit`.
- `actualVsForecast` is the source's own better/worse judgement (`null` when neutral, missing or the event has no usual effect).
- `currency` is `ALL` for worldwide events (Forex Factory's OPEC / G20 / IMF rows), with `country` and `countryCode` set to `null`.
- `detail` is only present when `includeDetails` is on. Forex Factory specs keys depend on the event (`source`, `sourceUrl`, `measures`, `usualEffect`, `frequency`, `acroExpand`, `eventType`, ...); Investing.com provides `source`, `sourceUrl` and `category`.

A source that could not be read produces a single free record with `status: "unavailable"` (or `"empty"`) and a `message` containing the HTTP status and a body snippet, so your pipeline can tell "no events" from "source down".

### Integrations

- **API**: start runs and read results with the [Apify API](https://docs.apify.com/api/v2) or the JavaScript and Python clients. Run the Actor synchronously with `run-sync-get-dataset-items` to get the week's events in one call.
- **MCP / AI agents**: the Actor is exposed through the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp) at `https://mcp.apify.com`. Add it to Claude Desktop, Cursor, ChatGPT or any MCP-capable trading agent, enable this Actor as a tool, and the agent can call it with the same input (for example `{"impact": ["high"], "currencies": ["USD"], "dateFrom": "2026-10-12", "dateTo": "2026-10-16"}`) to plan around releases. No custom MCP server is needed; the Actor's input schema becomes the tool schema.
- **n8n and Make**: use the Apify node or module, pick this Actor, pass the input JSON above and map the dataset items into your workflow.
- **Schedules and webhooks**: run it every morning from Apify Schedules and let a webhook push the day's high-impact events to Slack, Telegram, Google Sheets or your database.

### Sources and limitations

**Forex Factory (`forexfactory`, stable).** Read from the public calendar page (`forexfactory.com/calendar?range=...`), which answers plain HTTPS requests without login. Verified on 2026-10-10: a one-week window returned 109 events with correct UTC times, 13 of them high impact, and a past window returned actuals, revisions and better/worse markers. The site is behind Cloudflare; if a proxy IP is challenged the Actor falls back to the weekly JSON feed (`nfs.faireconomy.media/ff_calendar_thisweek.json`), which only covers the current week and has no actual values - that fallback is logged as a warning on the run. The `nextweek` and `lastweek` feed variants return 404 at the time of writing. Forex Factory covers the nine major currencies plus CNY and worldwide events; it does not list emerging-market calendars. Per-event details cost one extra request per distinct event type and are fetched only for events that survive your filters.

**Investing.com (`investing`, experimental).** Read from the JSON API behind the website's calendar. Verified on 2026-10-10: a three-day window returned 172-173 events across 26 currencies directly and through Apify datacenter proxy, including exchange holidays. The limitation is the site's web application firewall: it answers a bare `403` for some datacenter and residential proxy IPs and runs a Cloudflare JavaScript challenge for clients without a browser TLS fingerprint. The Actor retries a `403` with a fresh proxy session, and if the API still refuses it pushes a free `unavailable` status record with the status code and body snippet instead of inventing data. Investing.com does not expose "tentative" or "all day" flags, so `isTentative` is always `false` there and all-day holidays come from the holidays endpoint. Reported values are numeric with a `precision`; the Actor renders the display strings from them (`197` + `K` + precision 0 becomes `"197K"`).

**Both sources** publish figures as they are released and can revise them later; `scrapedAt` tells you when the record was taken. Times for events without a fixed slot (holidays, multi-day meetings, "tentative" data) are placeholders chosen by the source.

### Economic Calendar Scraper FAQ

#### Can I get only high-impact events for one currency?

Yes - set `impact: ["high"]` and `currencies: ["USD"]`. Filtering runs before charging, so you pay only for the events you receive.

#### How far back or ahead can I go?

Forex Factory serves any historical or future window; the Actor splits long windows into 62-day requests, up to 367 days per run. Investing.com's API also serves past and future dates. Actual values exist only for releases that have already happened.

#### Are the times in my timezone?

`datetimeUtc` is always UTC; convert it on your side. `timeLocalLabel` and `date` reflect the source's display timezone (`sourceTimezone`), which is US Eastern for Forex Factory - the same convention Forex Factory users are used to.

#### Why do I see `ALL` as a currency?

Forex Factory tags worldwide events (OPEC meetings, G20, IMF) with "All". Include `ALL` in `currencies` if you filter by currency and still want them.

#### What happens if a source is down?

The run still succeeds with the other source(s), and a free `unavailable` record explains what failed (HTTP status and body snippet). Nothing is faked.

### Related actors

Same author, same pay-per-event model and the same no-login approach. They combine well in one pipeline (for example calendar events plus prediction odds plus channel chatter around a release):

- [Telegram Channel Scraper](https://apify.com/romajure/telegram-channel-scraper) - posts, views, media and links from public Telegram channels, no login.
- [Substack Scraper](https://apify.com/romajure/substack-scraper) - posts, authors, likes, restacks and comments from public Substack publications, custom domains included.
- [Prediction Market Odds Scraper](https://apify.com/romajure/prediction-market-odds) - Polymarket and Kalshi markets with 0-1 prices, implied probabilities, bid/ask, volume and orderbooks.
- [Product Hunt Scraper](https://apify.com/romajure/product-hunt-scraper) - daily, weekly and monthly leaderboards, topic pages, search and product launches with votes, makers and website URLs.

### Legal and compliance

This Actor only reads publicly available pages and endpoints that the sources serve to anyone without logging in, and it does not bypass any access control or CAPTCHA. Economic calendar facts (release times, official figures) are public data, but each site's presentation is subject to its own terms: see [Forex Factory's terms](https://www.forexfactory.com/notices#terms) and [Investing.com's terms of use](https://www.investing.com/about-us/terms-and-conditions). You are responsible for using the data in line with those terms and applicable law, especially for commercial redistribution. Keep request rates low (the Actor already serializes requests with a delay) and read Apify's article on the [legality of web scraping](https://blog.apify.com/is-web-scraping-legal/) if you are unsure.

### Support

Found an event that parses wrongly, a missing currency, or need another source (ECB, FOMC schedules, earnings)? Open an issue on the Actor's **Issues** tab in Apify Console or contact the author through the Actor page. Reports that include the input JSON and the event title are usually fixed within days.

# Actor input Schema

## `sources` (type: `array`):

Which calendars to read. `forexfactory` is the stable source (full range, actuals, revisions, details). `investing` is experimental: its API sits behind a Cloudflare challenge and may return nothing from datacenter IPs; the run reports the failure instead of faking results.

## `dateFrom` (type: `string`):

First calendar day to include, ISO date `YYYY-MM-DD` (UTC). Defaults to today.

## `dateTo` (type: `string`):

Last calendar day to include (inclusive), ISO date `YYYY-MM-DD`. Defaults to seven days after `dateFrom`. Windows longer than 62 days are fetched in several requests.

## `currencies` (type: `array`):

Optional filter: only keep events for these ISO currency codes, e.g. `USD`, `EUR`, `GBP`. Forex Factory tags worldwide events (OPEC, G20) as `All`; include `ALL` to keep them.

## `impact` (type: `array`):

Optional filter on expected market impact. Leave empty for everything.

## `includeDetails` (type: `boolean`):

Fetch the per-event description where the source offers one (Forex Factory: one extra page per distinct event type with source, measures, usual effect, frequency; Investing.com: description and source from the same response). Slower for Forex Factory.

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

Proxy settings. Apify Proxy is recommended so the sources see a normal residential or datacenter browser session.

## Actor input object example

```json
{
  "sources": [
    "forexfactory"
  ],
  "currencies": [],
  "impact": [],
  "includeDetails": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `events` (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 = {
    "sources": [
        "forexfactory"
    ],
    "currencies": [],
    "impact": [],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("romajure/economic-calendar").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 = {
    "sources": ["forexfactory"],
    "currencies": [],
    "impact": [],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("romajure/economic-calendar").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 '{
  "sources": [
    "forexfactory"
  ],
  "currencies": [],
  "impact": [],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call romajure/economic-calendar --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,romajure/economic-calendar"
        }
    }
}
```

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/vPbrYD03PVvdVglJR/builds/56KqVchoyiTMUfgMU/openapi.json
