Forex Factory Economic Calendar Scraper
Pricing
from $0.02 / 1,000 item extracteds
Forex Factory Economic Calendar Scraper
π Export current-week Forex Factory macro events with stable IDs, currency, impact, forecast, previous value, local schedule, and canonical URLs. Filter records for trading-risk dashboards, alerts, and market-data pipelines.
Pricing
from $0.02 / 1,000 item extracteds
Rating
5.0
(1)
Developer
Automation Lab
Maintained by CommunityActor stats
0
Bookmarked
53
Total users
12
Monthly active users
13 days ago
Last modified
Categories
Share
Export the current-week Forex Factory economic calendar as clean JSON, CSV, Excel, XML, or RSS-ready dataset records.
Get event titles, currencies, local dates and times, impact levels, forecasts, previous values, stable IDs, and canonical Forex Factory URLs without a login or API key.
This Actor is designed for repeat schedules: trading-risk dashboards, market alerts, quantitative pipelines, newsletters, and research notebooks can refresh the same structured contract throughout the week.
CSV/XML does not declare a timezone. Legacy local fields and
timezone: nullstay unchanged. Opt in to source-backed UTC timestamps from uniquely matched offset-bearing JSON records; missing or conflicting evidence remains null.
This is an unofficial tool, not affiliated with or endorsed by Forex Factory or Fair Economy.
What does Forex Factory Economic Calendar Scraper do?
The Actor fetches Forex Factory's public current-week structured feed and turns every valid macroeconomic event into a normalized dataset row.
It can:
- π extract this week's economic calendar events;
- π± select currencies such as USD, EUR, GBP, JPY, CAD, AUD, NZD, or CHF;
- π¨ select High, Medium, Low, or Holiday impact levels;
- π restrict results to an inclusive local-date window and literal title keyword;
- π optionally enrich events with source-backed UTC timestamps;
- π inspect full-feed coverage, truncation and enrichment in the run summary;
- π§© create a deterministic event ID for deduplication;
- π preserve the canonical Forex Factory event URL;
- π€ export results through Apify datasets and integrations.
The minimum product intentionally stays on the proven public current-week feed. It does not claim arbitrary historical coverage.
Who is it for?
Traders and risk managers
Build a weekly risk calendar before entering positions. Filter to High-impact USD or EUR releases and send the records to an alerting tool.
Quantitative and market-data teams
Load normalized event schedules into a warehouse, join them to price series, and use stable IDs to avoid duplicate processing.
Newsletters and research desks
Create a repeatable list of upcoming macro events, forecasts, and previous values for briefing documents.
Automation builders
Run the Actor on a schedule and connect the dataset to Slack, Google Sheets, webhooks, Make, Zapier, or custom code.
Why use this economic calendar extractor?
Forex Factory presents useful macroeconomic information, but automation needs a stable machine-readable contract.
This Actor adds:
- normalized dates in
YYYY-MM-DDformat; - normalized clock times in 24-hour format when available;
- safe timezone handling with
timezone: nullwhen the feed is silent; - null preservation for blank forecasts and previous values;
- stable IDs derived from event identity fields;
- bounded retries and validation instead of silent empty output;
- pay-per-event billing aligned with produced data.
What data can I extract?
| Field | Type | Description |
|---|---|---|
eventId | string | Stable 24-character event identifier |
title | string | Economic event title |
currency | string | Three-letter affected currency code |
localDate | string | Source-local date in YYYY-MM-DD |
localTime | string | 24-hour time, All Day, Tentative, or Unscheduled |
localDateTime | string or null | Timezone-free local datetime when a clock time exists |
timezone | null | Always null; CSV/XML declares no timezone or IANA zone |
sourceDateTime | string or null | Exact offset-bearing JSON date for a unique compatible match; null otherwise |
eventDateTimeUtc | string or null | UTC ISO instant converted from sourceDateTime; null otherwise |
impact | string | High, Medium, Low, or Holiday |
forecast | string or null | Forecast value exactly as supplied |
previous | string or null | Previous value exactly as supplied |
url | string | Canonical Forex Factory calendar URL |
source | string | Forex Factory |
scrapedAt | string | UTC extraction timestamp |
How to scrape the Forex Factory calendar
- Open the Actor input page.
- Set Maximum events to the number you need.
- Optionally add currency codes such as
USDandEUR. - Optionally select impact levels such as
High. - Optionally enter
dateFromanddateTousingYYYY-MM-DD. - Click Start.
- Open the dataset to preview or export the economic events.
- Add a schedule if you need recurring refreshes.
The Console prefill/example saves 10 events; omitted maxItems defaults to 100. Use 500 for a broad weekly export, and inspect SUMMARY.truncated rather than assuming a capped dataset covers the whole week.
Input parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
maxItems | integer | 100 | Maximum matching events to save, from 1 to 500 |
currencies | string[] | [] | Optional three-letter currency filters |
impacts | string[] | [] | Optional High, Medium, Low, or Holiday filters |
dateFrom | string | unset | Inclusive source-local start date |
dateTo | string | unset | Inclusive source-local end date |
keyword | string | "" | Trimmed, case-insensitive literal substring of title |
includeUtcTimestamp | boolean | false | Request optional source-backed UTC fields; inspect summary status |
Empty filter arrays include all source values. Currency matching is case-insensitive; impact labels are case-sensitive. Keyword filtering is a literal title substring, not regex, whole-word matching, synonyms or sentiment. Empty/whitespace keyword includes all titles. Filters are AND-combined; array entries match ANY selected value. The global limit applies after filtering and deduplication.
Invalid property/array element types, noninteger limits, impossible Gregorian dates (such as 2026-02-30), reversed ranges and unsupported impact values fail clearly before requests or charging. Valid leap days are accepted. Unknown optional properties are ignored.
Example input: high-impact USD events
{"currencies": ["USD"],"impacts": ["High"],"maxItems": 50}
For a broad weekly export:
{"maxItems": 500}
For a focused USD inflation risk calendar:
{"currencies": ["USD"],"impacts": ["High"],"keyword": "CPI","includeUtcTimestamp": true,"maxItems": 50}
A legitimate zero-match week is possible. Do not substitute guessed timestamps when UTC enrichment is unavailable.
For a major-currency risk monitor:
{"currencies": ["USD", "EUR", "GBP", "JPY"],"impacts": ["High", "Medium"],"maxItems": 200}
Example output
{"eventId": "37d74dd9479b359e70134b18","title": "BusinessNZ Services Index","currency": "NZD","localDate": "2026-07-12","localTime": "22:30","localDateTime": "2026-07-12T22:30:00","timezone": null,"sourceDateTime": null,"eventDateTimeUtc": null,"impact": "Low","forecast": null,"previous": "47.5","url": "https://www.forexfactory.com/calendar/852-nz-businessnz-services-index","source": "Forex Factory","scrapedAt": "2026-07-16T02:30:00.000Z"}
Values such as percentages or abbreviations remain strings because the source may include units and revisions.
Local time and timezone semantics
The public current-week export provides a date and time but does not declare an IANA timezone or UTC offset in the complete CSV/XML record.
Accordingly:
localDatepreserves the calendar date;localTimenormalizes ordinary clock times to 24-hour form;localDateTimecombines those values without a timezone suffix;timezoneis alwaysnull;- all-day or tentative events have
localDateTime: null.
When includeUtcTimestamp: true, the Actor separately reads the current-week JSON feed. It joins only unique records by exact trimmed title, currency, and JSON date converted to a UTC clock equal to the full CSV/XML localDateTime, with compatible impact. This is a conservative cross-feed matching rule, not a claim that CSV/XML declares a timezone.
For example, a base schedule 2026-09-27T23:50:00 can match the JSON date 2026-09-27T19:50:00-04:00 and produce eventDateTimeUtc: "2026-09-27T23:50:00.000Z". The offset is applied once; it is not converted into an IANA zone. Positive offsets and day rollover follow the JSON instant, never a global offset assumption.
Disabled enrichment, ambiguous keys, missing/invalid offsets, incompatible impact or time, all-day/tentative/unscheduled labels, and cross-feed disagreement leave the two additive fields null. If JSON fails, useful base rows still succeed; the summary says unavailable. At most two JSON requests, each with a 10-second timeout, are made, direct first then fresh proxy. No browser or per-event request is used. Date filters still use localDate; enabling UTC does not change them.
Coverage and extraction summary
Open Coverage and UTC enrichment summary in the Output tab or read SUMMARY in this run's default key-value store. It costs no item event. SOURCE_SAMPLE remains the first unnormalized base event.
The summary records source URL/format/route, scrape time and observed valid source-local date bounds. Counts cover the entire acquired feed, not just the saved prefix:
sourceCount: all acquired records.malformedCount: records rejected by base validation; partial malformed feeds warn explicitly.validCount: valid records including duplicates (sourceCount - malformedCount).duplicateCount: valid repeated event IDs, removed before filtering.filteredCount: unique valid records rejected by one or more filters, counted once.matchingCount: unique valid records passing every filter, before the cap.savedCount: rows actually saved;maxItemsis the cap.truncated: matching count exceeds the cap; 143 matches at a cap of 100 means 100 saved andtrue.
Thus validCount = duplicateCount + filteredCount + matchingCount. A valid zero-match run says resultReason: "no_filter_matches"; an empty or entirely malformed base feed fails non-zero rather than claiming zero matches.
utcEnrichment records requested status (not_requested, complete, degraded or unavailable), source URL and join provenance. Its matchedCount/unmatchedCount partition all matching unique rows before the cap when requested; both are zero when disabled. savedMatchedCount counts enriched saved rows. complete means all matching rows were enriched, not an assertion of complete source history. Always inspect null fields and summary status before timing-sensitive automation.
Stable IDs and scheduled monitoring
The eventId is derived from title, currency, date, time, and canonical URL.
For scheduled workflows:
- store the latest dataset in your database;
- use
eventIdas a natural deduplication key; - compare forecasts or previous values when the same ID reappears;
- alert only when a record is new or changed.
IDs are stable for unchanged source records, but a corrected source schedule can intentionally produce a new ID.
How much does it cost to scrape Forex Factory events?
The Actor uses pay-per-event pricing. A run costs $0.005 to start, then one item event per saved economic event.
| Apify tier | Price per saved event | 100 events plus start |
|---|---|---|
| Free | $0.000042972 | about $0.00930 |
| Bronze | $0.000037367 | about $0.00874 |
| Silver | $0.000029146 | about $0.00791 |
| Gold | $0.000022420 | about $0.00724 |
| Platinum | $0.000014947 | about $0.00649 |
| Diamond | $0.000010463 | about $0.00605 |
Input filters and maxItems let you cap output and spending. A valid run that saves 20 events charges one start event and 20 item events. Filtered-out records, duplicate records and the summary are not item-charged. A valid zero-match run charges only start. Enrichment adds no new charge event. Invalid input is rejected before the start charge.
Tips for reliable calendar workflows
- ποΈ Run on a schedule appropriate for your dashboard, not every minute by default.
- π¨ Use impact filters when only market-moving releases matter.
- π± Use uppercase ISO-style codes in documentation, although input matching is case-insensitive.
- π Deduplicate on
eventId, not title alone. - π Treat local schedule fields as timezone-free unless you verify the source convention.
- π¦ Export the dataset after each run or consume it through the API.
- π Preserve null forecasts; a blank value is different from zero.
Integrations and automation patterns
Google Sheets briefing
Schedule the Actor before a weekly trading meeting and export the dataset to a Sheet sorted by local date and impact.
Slack or email risk alerts
Filter to High-impact currencies, compare IDs against the prior run, and post new events to a risk channel.
Data warehouse ingestion
Use a webhook to copy completed dataset rows into BigQuery, Snowflake, PostgreSQL, or another warehouse.
Market-research notebook
Fetch dataset JSON in Python and join local event schedules to independently timezone-normalized market data.
Make and Zapier
Trigger a run on a schedule, iterate dataset rows, and route events by currency or impact.
API usage with JavaScript
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('automation-lab/forex-factory-economic-calendar-scraper').call({currencies: ['USD', 'EUR'],impacts: ['High'],maxItems: 50,});const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(items);
Python API example
import osfrom apify_client import ApifyClientclient = ApifyClient(os.environ['APIFY_TOKEN'])run = client.actor('automation-lab/forex-factory-economic-calendar-scraper').call(run_input={'currencies': ['USD', 'EUR'],'impacts': ['High'],'maxItems': 50,})items = client.dataset(run['defaultDatasetId']).list_items().itemsprint(items)
cURL API example
curl -X POST \"https://api.apify.com/v2/acts/automation-lab~forex-factory-economic-calendar-scraper/runs?token=$APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"currencies":["USD"],"impacts":["High"],"maxItems":50}'
After the run succeeds, read its defaultDatasetId and request /v2/datasets/{DATASET_ID}/items.
Use with Apify MCP
Connect Claude Code with:
$claude mcp add --transport http apify "https://mcp.apify.com?tools=automation-lab/forex-factory-economic-calendar-scraper"
For Claude Desktop, Cursor, or VS Code, add an HTTP MCP server configuration:
{"mcpServers": {"apify": {"url": "https://mcp.apify.com?tools=automation-lab/forex-factory-economic-calendar-scraper"}}}
Follow one run and read bounded results
The Actor-specific endpoint selects a stable subset, not exactly one tool: it also includes get-actor-run, get-dataset-items, get-key-value-store-record, and abort-actor-run. Use scoped tools/list to discover the actual names and argument schemas, then load only the Actor/run/data helpers you need. Read-only discovery does not authorize execution or aborting a run.
- Start once when authorized. Retain the returned run ID, status and storage IDs; these are metadata, not event rows.
call-actorwaits at mostwaitSecs(0β45 seconds, default 30), so it may return before completion. Set the client request timeout above the selected wait plus transport margin, within a total 120-second consumer deadline. - Follow the same run. If nonterminal, use
get-actor-runfor that ID with 2, 4, 8-second backoff capped at 10 seconds, stopping at the deadline. After a client timeout, recover/check the known run instead of starting another. If the ID is unknown, report uncertainty rather than blindly rerunning. At the deadline, report pending with the run ID and stop polling. Report terminal failures honestly; any available rows are partial, not a successful full extraction. - Read actual rows in pages. After success, use
get-dataset-itemswithdefaultDatasetId, explicitoffset: 0,limit: 20, and neededfieldssuch aseventId,title,currency,impact,localDateTime,eventDateTimeUtc,url, using the discovered argument schema. Prefer untransformed JSON. Track source offsets and pagination metadata, not transformed row counts, since filtering/unwinding can change counts. ReadSUMMARYthroughget-key-value-store-recordwhen coverage/enrichment status is needed. - Bound model context, not extraction. For example, admit at most 100 source rows and 64 KiB of serialized UTF-8 result content across all pages and summary, whichever comes first. Process responses host-side before injecting them into model context; omit or summarize an oversized row/page with disclosure. If your client cannot intercept oversized responses, this is not a hard byte guarantee: do not request unbounded results. Stop at exhaustion or budget, disclose returned rows, continuation offset, and any partial/truncated result. Keep full dataset exports in storage/downstream processing outside model context. This consumer budget does not change Actor defaults, collection scope or output fields.
These backoff/deadline/context values are example consumer choices, not Apify defaults. Discovery transport bytes are not model-visible context; host-side caching, progressive loading and prompt caching depend on client capabilities. No universal token savings are promised. A numeric savings claim would need the measured client/version, negotiated capabilities and cache mode, model/tokenizer, visible tool/result subset and baseline method.
Example prompts:
- βExtract this week's high-impact USD Forex Factory events.β
- βBuild a JSON list of medium- and high-impact EUR and GBP releases.β
- βCompare these event IDs with yesterday's dataset and summarize changes.β
Source coverage and limitations
The Actor covers the current public weekly feed available at run time.
It does not:
- crawl arbitrary historical date ranges;
- predict future values;
- provide trading advice;
- invent missing forecast or previous values;
- guess UTC instants from timezone-free local schedules;
- guarantee actual/revised values, arbitrary history, or next/last-week feeds;
- scrape private account data.
The upstream feed can revise event dates, times, values, or URLs. Scheduled users should treat each run as a fresh source snapshot.
Data quality and error handling
The extractor validates required titles, dates, currency codes, impact levels, and canonical event URLs.
Individual malformed records are skipped with warning logs. A missing feed root or a feed with no parseable events fails rather than returning a misleading empty success.
Requests use a finite timeout and bounded retries. The Actor spreads direct requests across the equivalent CSV and XML feeds. If both direct routes are throttled, it retries through fresh Apify Proxy identities; this can add a small amount of platform proxy transfer. The Actor explicitly decodes the feed's declared Windows-1252 encoding.
Data handling and AI
The Actor uses deterministic HTTP extraction and parsing. It does not call AI models or accept credentials/private account data. Run datasets, key-value stores and logs follow your Apify account retention settings and can be deleted with Apify storage controls.
Failed operations send sanitized diagnostic input, exceptions and Actor/build/run IDs to our private GlitchTip service for repair. Secret fields and URL query strings are removed; diagnostic reports are retained for 30 days. Successful optional-feed recovery warnings are not terminal failure reports.
Legality: is scraping Forex Factory legal?
This Actor reads an anonymously accessible public structured feed and does not bypass login controls.
You are responsible for your use of the data, including compliance with applicable laws, contracts, Forex Factory terms, intellectual-property rights, and privacy obligations.
Use reasonable schedules, avoid unnecessary load, and do not present the output as investment advice.
FAQ
Does the Actor need a Forex Factory account?
No. The current-week feed used by this Actor is publicly accessible without a login or API key.
Can I scrape last month or any custom historical range?
Not in v1. The reliable product scope is the public current-week feed. Date filters narrow that feed; they do not request historical pages.
Why is timezone null?
The complete CSV/XML record does not declare a timezone. Returning null is safer than inventing an offset that could move an event to the wrong instant.
Why are some forecasts or previous values null?
Forex Factory leaves some values blank, especially before estimates are available. The Actor preserves blanks as null rather than treating them as zero.
Why did my filtered run return no events?
The selected currencies, impacts, keyword or local date range may not occur in the current weekly feed. Inspect SUMMARY for source/matching/saved counts, remove filters or inspect the broad weekly export.
Why did the run reject my date?
Use a real Gregorian YYYY-MM-DD date, for example 2026-07-16. Impossible dates are rejected. Ensure dateFrom is not later than dateTo.
Can I stop after a fixed number of records?
Yes. Set maxItems from 1 to 500. It applies after filtering.
Can I use the output for automated trading?
You can integrate it into your own systems, but verify timing and data independently. The Actor is a data extraction tool, not financial advice.
Related scrapers
Combine this Actor with other automation-lab data tools:
- Trading Economics Indicators Scraper for broader indicator datasets.
- SEC 8-K Current Reports Scraper for market-moving company filings.
- US Treasury Fiscal Data Scraper for official fiscal series.
Choose this Actor when your workflow specifically needs the Forex Factory current-week event feed.
Support
If a run fails unexpectedly, share the run URL and a minimal input that reproduces the issue through the Actor page.
Useful details include:
- the currency and impact filters used;
- the local date range;
- whether an unfiltered run worked;
- the expected event title or URL.
These details make source-feed changes and parser regressions faster to diagnose.