Canada Federal Contract Awards Scraper
Pricing
$3.00 / 1,000 contract returneds
Canada Federal Contract Awards Scraper
Awarded Canadian federal contracts over CA$10,000 from the Government of Canada Proactive Publication open data: vendor, value, department, dates, procedure.
Pricing
$3.00 / 1,000 contract returneds
Rating
0.0
(0)
Developer
Jason
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
7 days ago
Last modified
Categories
Share
Pulls awarded Canadian federal contracts from the Government of Canada's proactive publication of contracts over CA$10,000 - the quarterly disclosure every federal department must make under section 86 of the Access to Information Act - through the open.canada.ca CKAN datastore API. No API key, no browser automation, no login. You get one flat JSON record per disclosed contract or amendment: the winning vendor and its postal area, the department, the total, original and amendment values in CAD, the contract and delivery dates, the solicitation procedure (competitive or sole-source, with the limited-tendering reason spelled out), the trade agreements that covered it, the number of bids, and a link to the contract's own page on the Treasury Board search site. Filter by contract date, reporting quarter, department, vendor, keyword and minimum value. This is the award side of Canadian procurement - who actually won, and for how much - not the CanadaBuys tender feed of open opportunities. The datastore held 1,313,551 contract rows on 8 September 2026.
What you get
Every record contains:
id-<departmentCode>:<referenceNumber>,source(open.canada.ca/contracts),url- the contract's page atsearch.open.canada.ca/contracts/record/...,referenceNumber(the department's unique row id, for exampleC-2026-2027-Q1-00664),procurementId(the contract number; the same value ties an original contract to its later amendments)department,departmentFr,departmentCode- the reporting entity, English and French names plus theowner_orgcode (rcmp-grc,dnd-mdn,pc, ...)vendorName,vendorPostalCode(first three characters of the Canadian postal code - the forward sortation area, which is all the source publishes),vendorCountry(ISO 3166 alpha-2),vendorCountryNamebuyerName- the departmental buyer named on the contract (see the personal-data note below)contractDate(award date),contractPeriodStart,deliveryDate- allYYYY-MM-DDcontractValue,originalValue,amendmentValueas numbers,currency(alwaysCAD),isAmendment(true when a non-zero amendment value is published)description,descriptionFr- the economic-object description, andcomments- the department's own note on the contracteconomicObjectCode,commodityCode,commodityType+commodityTypeLabel(Good,Service,Construction)solicitationProcedure+solicitationProcedureLabel(Competitive – Open Bidding (GETS),Competitive – Selective Tendering,Competitive – Traditional,Advance Contract Award Notice,Non-Competitive) andisCompetitive, a boolean shortcut over those five codeslimitedTenderingReason+limitedTenderingReasonLabel- why a sole-source award was allowed (Exclusive rights,Extreme urgency,Prototype purchase, ...)tradeAgreement(the raw published code list),tradeAgreements(array of codes, with theXX"none" marker removed),tradeAgreementLabels(Canadian Free Trade Agreement,World Trade Organization – Agreement on Government Procurement, ...)numberOfBids,awardCriteria+awardCriteriaLabel(Lowest Price,Highest Combined Rating of Technical Merit and Price, ...)instrumentType+instrumentTypeLabel,standingOfferNumber,contractingEntity+contractingEntityLabel(who ran the buy: the department itself, PSPC, or a call-up against a standing offer)indigenousBusiness+indigenousBusinessLabel,intellectualProperty,formerPublicServant,ministersOffice(booleans for the last two)reportingPeriod- the fiscal quarter the row was disclosed in,YYYY-YYYY-QnfetchedAt- ISO timestamp of the run
Every code field keeps the government's own code and an English label, decoded from the dataset's published schema, so the output is readable without a separate lookup table.
The dataset has three views: Overview (date, department, vendor, description, value, procedure), Vendors (vendor, postal area, country, total/original/amendment values, buyer, dates) and Competition (competitive flag, procedure, limited-tendering reason, bid count, trade agreements, award criteria).
Input
| Field | Type | Default | Description |
|---|---|---|---|
daysBack | integer | 30 | Width of the contract-date window. Ignored when dateFrom is set, and ignored entirely when reportingPeriods is used on its own. |
dateFrom | string | - | Earliest contract date, YYYY-MM-DD (inclusive). |
dateTo | string | - | Latest contract date, YYYY-MM-DD (inclusive). Setting it turns the anchor off and uses your date literally. |
anchorToLatestData | boolean | true | End the window at the newest contract date the source actually holds instead of at today. See the warning below - with this off, a default run returns nothing for most of the year. |
reportingPeriods | string[] | none | Fiscal quarters as published, YYYY-YYYY-Qn (2026-2027-Q1 = April-June 2026). Selects whole quarterly releases, amendments to old contracts included. Replaces the days-back window; add dateFrom/dateTo to intersect the two. |
departments | string[] | all | Case-insensitive substrings matched against the department code and its bilingual title: dnd-mdn, National Defence, Défense, Parks. |
vendors | string[] | all | Case-insensitive substrings matched against the vendor name: Deloitte, IBM, Commissionnaires. Any term matching keeps the record. |
keywords | string[] | none | Case-insensitive terms matched against the English and French description, the departmental comments, the commodity code and the economic object code. |
minValue | integer | 0 | Keep only contracts worth at least this many CAD. Contracts with no published value drop out once this is set. |
maxItems | integer | 500 | Stop after this many contracts, newest contract date first. You are charged per contract delivered, so this is the cost cap; anything smaller than the window's volume drops the oldest contracts in it. |
The window is anchored to the data, not to today - and that is deliberate. Departments publish quarterly, up to 30 days after the end of Q1-Q3 and 60 days after Q4, so "the last 30 days" measured from the calendar is empty for most of the year. On 8 September 2026 the newest quarter on file was 2026-2027-Q1 (April-June 2026) and the newest real contract date was 2026-07-23; a window ending "today" returned zero rows. With anchorToLatestData on (the default) the same run returns the newest 1,060 contracts instead. Set anchorToLatestData: false when you want a literal calendar window - for example to prove a quarter has not landed yet.
Example - National Defence IT contracts of at least CA$1 million in the latest published quarter:
{"reportingPeriods": ["2026-2027-Q1"],"departments": ["dnd-mdn"],"keywords": ["informatics", "information technology", "software"],"minValue": 1000000,"maxItems": 500}
Example - everything one vendor won across a fiscal year:
{ "vendors": ["Deloitte"], "dateFrom": "2025-04-01", "dateTo": "2026-03-31", "maxItems": 2000 }
Bad input fails fast: a malformed reporting period, a malformed date, an inverted window or a range longer than 3,660 days stops the run with the validation message as its status before any data is fetched.
Output example
A real record from a live run on 8 September 2026 (input {"reportingPeriods": ["2026-2027-Q1"], "vendors": ["Deloitte"], "maxItems": 3}), with the twelve tradeAgreementLabels trimmed to three:
{"id": "rcmp-grc:C-2026-2027-Q1-00664","source": "open.canada.ca/contracts","url": "https://search.open.canada.ca/contracts/record/rcmp-grc%2CC-2026-2027-Q1-00664","referenceNumber": "C-2026-2027-Q1-00664","procurementId": "7285834","department": "Royal Canadian Mounted Police","departmentFr": "Gendarmerie royale du Canada","departmentCode": "rcmp-grc","vendorName": "DELOITTE INC.","vendorPostalCode": "K1P","vendorCountry": "CA","vendorCountryName": "Canada","buyerName": "Wright, Connie","contractDate": "2026-06-11","contractPeriodStart": "2026-06-22","deliveryDate": "2027-06-18","contractValue": 7614867.26,"originalValue": 7614867.26,"amendmentValue": 0,"currency": "CAD","isAmendment": false,"description": "Information technology and telecommunications consultants","descriptionFr": "Consultants en TI et en télécommunications","comments": null,"economicObjectCode": "473","commodityType": "S","commodityTypeLabel": "Service","commodityCode": "D302","solicitationProcedure": "OB","solicitationProcedureLabel": "Competitive – Open Bidding (GETS)","isCompetitive": true,"limitedTenderingReason": "00","limitedTenderingReasonLabel": "None","tradeAgreement": "CA,CL,CO,EU,GP,HN,KR,PA,PE,TP,UA,UK","tradeAgreements": ["CA", "CL", "CO", "EU", "GP", "HN", "KR", "PA", "PE", "TP", "UA", "UK"],"tradeAgreementLabels": ["Canadian Free Trade Agreement","Comprehensive Economic Free Trade Agreement","World Trade Organization – Agreement on Government Procurement"],"numberOfBids": 2,"awardCriteria": "3","awardCriteriaLabel": "Highest Combined Rating of Technical Merit and Price","instrumentType": "C","instrumentTypeLabel": "Contract","standingOfferNumber": null,"contractingEntity": "PWC","contractingEntityLabel": "Contract or Call-up awarded by PSPC on behalf of the client department.","indigenousBusiness": "NA","indigenousBusinessLabel": "None","intellectualProperty": "B","formerPublicServant": false,"ministersOffice": false,"reportingPeriod": "2026-2027-Q1","fetchedAt": "2026-09-08T02:23:25.807Z"}
An amendment from the same source looks the same but carries "amendmentValue": 17564.52, "isAmendment": true, a contractValue larger than originalValue, and usually a comments string explaining the change. contractValue is null only when the department published no figure.
The run also writes a SUMMARY record to the key-value store with the number of rows scanned and kept, how many each filter dropped, the resolved window, the newest contract date found in the source, and whether the department filter ran server-side.
Pricing
Pay per result: US$0.003 per contract delivered (US$3 per 1,000 contracts). You are charged only for records pushed to the dataset; a run that matches nothing costs nothing. Runs on the Apify free plan are limited by the platform's free-tier compute allowance.
Data source and licence
- Dataset: "Proactive Publication - Contracts", Treasury Board of Canada Secretariat, https://open.canada.ca/data/en/dataset/d8f85d91-7dec-4fd1-8055-483b77225d8b. The Actor reads the datastore-backed resource
fac950c0-00d5-4ec1-a4d3-9cbebf98a305("Contracts over $10,000") only. The dataset's other resources - the 2,470-row legacy extract, the 646-row aggregate of contracts under $10,000, and the 98-row "nothing to report" list - are not read. - Endpoint:
POST https://open.canada.ca/data/en/api/3/action/datastore_searchwithfilters,sort,limitandoffset, plus oneGET .../organization_list?all_fields=trueper run whendepartmentsis used. The 612 MB CSV export is never downloaded. - Statutory basis: section 86 of the Access to Information Act requires each entity to publish, for every contract over $10,000 entered into in a quarter, "the subject matter of the contract; the names of the parties; the contract period; the value of the contract; the reference number assigned to the contract, if any" - "within 30 days after the end of each of the first three quarters" and within 60 days after the fourth (https://laws-lois.justice.gc.ca/eng/acts/A-1/section-86.html, read 8 September 2026).
- Licence: Open Government Licence - Canada (
ca-ogl-lgo), read 8 September 2026. It grants a worldwide, royalty-free, perpetual right to copy, modify, publish and distribute the information, including for commercial purposes, on condition that you acknowledge the source. Attribute as "Contains information licensed under the Open Government Licence – Canada." - Personal data.
buyerNameis the name of the departmental buyer or contracting officer as printed on the contract ("Wright, Connie", "LAMPRON, ANNIE");vendorNameis often a sole trader's own name, andvendorPostalCodeis the first three characters of a postal code. The Government of Canada publishes these lawfully under the Access to Information Act, but that publication does not by itself make every downstream use lawful. If you use these fields - marketing in particular - the obligations under PIPEDA, CASL and any provincial privacy law are yours, not the source's. No email addresses or telephone numbers are published in this dataset. - The source's own caveat, repeated here: "the information contained in these Contracts reports have been derived from data provided by the authorized federal reporting entities. As the data is unaudited, no warranty" is given as to its accuracy.
Limits and freshness
- Publication is quarterly, and that dominates everything else. The dataset's declared update frequency is
P3M. On 8 September 2026 the newest quarter on file was 2026-2027-Q1 (April-June 2026, 23,292 rows); 2026-2027-Q2 held a single stray row. The newest contract date that is not in the future was 2026-07-23, and the bulk of the quarter ends at 2026-06-30. Scheduling this Actor daily will re-deliver - and re-charge for - the same records; schedule it monthly, or quarterly a few days after each publication deadline (roughly 30 July, 30 October, 30 January and 30 May). - The file still changes between quarters. The resource's
last_modifiedon 8 September 2026 was 2026-09-07: departments file late submissions and corrections continuously, so re-running an old window occasionally returns rows that were not there before. New award dates, however, only arrive when a quarter is published. - Volumes, measured 8 September 2026 by counting rows per window through the API: the default anchored 30-day window (2026-06-24 to 2026-07-23) held 1,060 contracts; 30-day windows inside a quarter held 5,236 (15 May - 13 June 2026) and 6,313 (15 April - 14 May 2026); the trailing 365 days held 74,391. Recent whole quarters: 2025-2026-Q1 19,295, Q2 19,706, Q3 23,400, Q4 28,260, 2026-2027-Q1 23,292. The busiest single day was fiscal year-end, 2026-03-31, with 518 contracts. 83 organisations reported in 2026-2027-Q1.
- Size
maxItemsto the window. It counts records kept after filtering, so a vendor, keyword or value filter usually keeps a run well inside the default 500. An unfiltered quarter does not:{"reportingPeriods": ["2026-2027-Q1"]}with the defaultmaxItems: 500returns the newest 500 of 23,292 and logslimitReached: true. Because the stream is newest-first, that truncation drops the oldest contracts in the window. - A reporting period is not a date range. 5,756 of the 23,292 rows disclosed in 2026-2027-Q1 have a contract date outside April-June 2026 (the oldest is 2003-07-28): they are amendments to older contracts, disclosed now. Use
reportingPeriodsto monitor what was newly disclosed, anddateFrom/dateToto select what was awarded in a period. - Date quality at the edges. Contract dates are department-keyed and a handful are wrong: two rows are dated after this run (2026-09-26 and 2026-12-01) and two are dated 1899-12-30 and 1900-02-24. The Actor ignores future dates when it looks for the newest published contract date, but it does not otherwise correct them. The oldest plausible date in the file is 1999-01-11; reporting periods go back to 1995-1996-Q1.
- What the API can and cannot do.
filterssupports exact matches and value lists, so the contract-date window (one exact date per day), the reporting periods and the resolved department codes all run server-side. Full-text search (q) is refused on this resource - "Full text search is not supported for data with more than 100000 rows" - and thedatastore_search_sqlaction is not enabled, so vendor, keyword and minimum-value filters are applied locally after fetching. Those runs read the whole window: budget for it. - Throughput and rate limits. Pages are 1,000 rows (the API allows up to 32,000; 1,000 keeps each response near 1.5 MB) with a 250 ms pause between them. Scanning a whole quarter - 23,292 rows, 24 pages, deep offsets included - took 1 minute 43 seconds end to end on 8 September 2026; a filtered run that stops at
maxItemstakes seconds. Twelve consecutive requests returned HTTP 200 with no throttling, and the API publishes no documented rate limit;fetchWithRetrystill backs off exponentially on 429 and 5xx. - User-Agent gotcha. open.canada.ca sits behind a WAF that answers
403 Forbiddento any request whoseUser-Agentcontains the substring "Operator" (measured 8 September 2026:Foo/1.0andpython-requests/2.32get 200,Operatorgets an nginx 403 page). This Actor sends its own agent string; if you fork it, keep that word out of the header. - Windows longer than 3,660 days (10 years) are rejected rather than silently truncated; split them across runs. Longer windows are split internally into 366-day chunks read newest-first, so ordering holds across the whole range.
- Records are de-duplicated within a run on
departmentCode:referenceNumber, which is unique per quarter (verified across all 23,292 rows of 2026-2027-Q1). Across quarters, an amended contract reappears under a newreferenceNumberwith the sameprocurementId- group onprocurementIdto rebuild a contract's history.
Use cases
- Competitor and incumbent intelligence. Pull every contract a rival won last quarter - value, department, delivery date, standing-offer number - and diary the re-compete before the delivery date lands.
- Government-sales prospecting. Filter by commodity code or keyword to find the departments actually buying what you sell, how much they spent, whether they bought competitively, and which buyer signed it off.
- Oversight, journalism and research. Track sole-source awards (
isCompetitive: falsewith the limited-tendering reason), single-bid "competitive" contracts, ministers' office contracts, former-public-servant contracts, or amendment creep betweenoriginalValueandcontractValueacross a whole fiscal year.
Support
Open an issue on the Actor's Issues tab on Apify Store. Replies within 14 days. Bug reports that name the run id and the input used are fixed fastest.