Tender Data API – EU European Tenders, TED Europa, CPV Codes avatar

Tender Data API – EU European Tenders, TED Europa, CPV Codes

Pricing

$1.50 / 1,000 result items

Go to Apify Store
Tender Data API – EU European Tenders, TED Europa, CPV Codes

Tender Data API – EU European Tenders, TED Europa, CPV Codes

Search the EU's official TED public-procurement journal by country, CPV code, date or open submission deadline. Returns clean, deduplicated JSON in your choice of 24 EU languages: buyer, value, deadlines, CPV codes and notice link. Includes tender notices, contract awards and corrigenda.

Pricing

$1.50 / 1,000 result items

Rating

0.0

(0)

Developer

Fetch Smith

Fetch Smith

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

an hour ago

Last modified

Share

EU & European Tenders (TED) — Public Procurement & Government Tenders Europe Scraper

Search TED (Tenders Electronic Daily), the EU's official public-procurement journal, and get clean, structured JSON back — no EU login, no scraping tricks, just the official free api.ted.europa.eu Search API normalized into a usable shape.

Use cases

  • Bids and tenders monitoring — track new contract notices in your CPV codes and countries so a sales team hears about a tender the day it's published, not weeks later browsing ted.europa.eu by hand.
  • Government-spending research & journalism — pull every notice for a buyer, country or sector over a date range with contract value, buyer and deadline already flattened into one row.
  • Market-sizing — aggregate totalValue/totalValueCurrency across CPV codes or countries to estimate how much a government is spending in a given category.
  • Lead generation — buyerEmail/buyerPhone/buyerUrl give a direct contact point for the procurement office behind each notice, most of them real role mailboxes (einkauf@…, vergabestelle@…).
  • Bid pipeline / deadline tracking — deadlineDate (earliest submission deadline across all lots), daysUntilDeadline and deadlineReceiptRequestDate let you build a reminder feed instead of re-checking the site. Set onlyOpenDeadlines to get only tenders you can still bid on, and minDaysUntilDeadline: 14 to skip the ones closing too soon to prepare a bid for.
  • Corrigendum tracking — a filter for noticeTypes plus procedureIdentifier lets you group a notice with any corrigenda published against the same procedure, and changeReasonDescription tells you in plain text what changed (deadline, specs, opening date) without opening the PDF.

Input

FieldTypeDescription
countriesarrayISO 3166-1 alpha-3 buyer country codes (e.g. DEU, FRA). Empty = all.
cpvCodesarray8-digit CPV codes to filter by (e.g. 72000000 for IT services). Empty = all. TED matches the entire CPV subtree under each code you supply, at every level of the hierarchy — there is no exact-code match. 72000000 returns notices tagged only 72313000 or 72220000, and even a narrow code like 72267000 returns its children 72267100/72267200. See the FAQ below for the measurement and the workaround.
noticeTypesarrayTED notice-type codes, picked from a dropdown of all 22 codes TED accepts (e.g. cn-standard contract notice, can-standard award notice, pin-only/pin-buyer/pin-rtl prior information, veat, corr, can-modif, qu-sy, pmc). Empty = all. There is no pin-standard code — see the FAQ.
procedureTypearrayTED procedure-type codes, picked from a dropdown of all 18 codes TED accepts: the 8 modern eForms codes (open, restricted, neg-w-call, neg-wo-call, comp-dial, oth-single, oth-mult, innovation), 9 legacy pre-2023 single-character codes, plus comp-tend (competitive tendering for public passenger transport, Reg. 1370/2007 art. 5(3)). Empty = all. Server-side filter, same OR-group as noticeTypes.
publishedWithinDaysintegerOnly notices published in the last N days. Default 7. Ignored if publicationDateFrom/publicationDateTo is set.
publicationDateFrom / publicationDateTostringAbsolute date window, YYYYMMDD or YYYY-MM-DD. Either or both — overrides publishedWithinDays.
keywordsstringFree-text search using TED's FT~ operator — matches the whole notice text TED indexes, not just title/description/buyer name (see FAQ).
expertQuerystringRaw TED expert-query string — overrides all the filters above entirely.
maxResultsintegerStop after this many notices. Default 100.
minValue / maxValueintegerOnly keep notices whose totalValue falls in this range. Compares the raw number regardless of currency (TED reports EUR, CZK, RON, SEK, etc. per notice — check totalValueCurrency). Roughly half of all notices carry no value at all; those are dropped whenever either is set.
onlyOpenDeadlinesbooleanKeep only notices whose submission deadline is today or later — the tenders you can still bid on. Notices with no published deadline (award/result notices, most prior-information notices) are dropped while this is on, since an absent deadline can't be shown to be open.
minDaysUntilDeadlineintegerKeep only notices with at least this many whole days left before the deadline (daysUntilDeadline in the output), counted in Brussels local time (the zone every TED deadline is stamped in). Implies onlyOpenDeadlines.
outputLanguagestringPreferred language for title/description/buyerName/buyerCity/noticeUrl (24 EU languages, e.g. deu, fra, spa). Default eng. Falls back to English, then to whatever TED provided, if a notice has no translation into your chosen language.
flattenbooleanDefault false (JSON arrays). Set true to join cpvCodes, contractNature, placeOfPerformanceCountry and placeOfPerformanceCity into a single comma-separated string per field, instead of a JSON array — cleaner for CSV/Excel export (Apify's default array export otherwise splits each into numbered field/0, field/1 columns that shift between rows with different array lengths).
watchLabelstringOptional. Name a saved query and get only what is new since your last run — see below.
webhookUrlstringOptional. POST a small JSON completion summary (notices pushed, pages scanned, TED's reported total, dataset ID, watch new count) here when the run finishes — see FAQ.

Example: German construction/engineering notices from the last 2 weeks

{
"countries": ["DEU"],
"cpvCodes": ["71000000"],
"publishedWithinDays": 14,
"maxResults": 100
}

Multiple values within one field (e.g. two country codes) are OR'd together; different fields (country AND CPV code) are AND'd. Leave every filter empty to pull all recent notices across the whole EU/EEA.

Only what's new since last run (watchLabel)

A bid-monitoring job is a subscription, not a search: you want the notices published since you last looked, not the same hundreds of rows re-delivered (and re-charged) every morning.

Set watchLabel to a name for the query — de-it-services, say — and this Actor keeps track of which notices it has already given you under that name:

  • The first run on a new label is a free baseline. It records what already matches, returns zero results and charges nothing. It walks notice ids only, not full notices.
  • Every run after that returns only the new notices. Already-delivered rows are dropped before they are built or billed, so you never pay for the same notice twice.
  • A notice counts as delivered only once it has actually been charged. Anything cut off by maxResults or a charge limit stays "new" for the next run rather than vanishing.
  • Changing a filter starts a fresh baseline — a different filter is a different question, so you don't get a dump of everything the old, narrower query happened to exclude. Setting expertQuery also starts its own baseline, keyed on the raw query string.
  • The rolling publishedWithinDays window is deliberately not part of that identity. It moves every day; if it counted, a daily schedule would re-seed forever and never deliver anything. publicationDateFrom/publicationDateTo, when you set them explicitly, do count.
  • Don't pin a fixed publicationDateTo on a watched query. publication-date is assigned once, at the moment TED publishes a notice, and is never revised afterward, so once the real calendar date passes a fixed cutoff, no notice can ever be dated on or before it again — the watch goes permanently quiet while still logging the same reassuring "0 new notices" every scheduled run. publicationDateFrom alone is safe to keep; only the upper bound is the trap. See the FAQ below.

The baseline lives in a key-value store named fetchsmith-ted-watch on your own account, so it survives between runs and you can inspect or reset it yourself. Point an Apify schedule at the Actor and you have a TED procurement alert.

Baseline size cap. A baseline holds up to 60,000 notice ids in one saved record. If a label's baseline grows past that, the oldest-first-seen ids are dropped — and a dropped id is no longer recognised, so that notice comes back as "new" on a later run and is charged again. The run that drops them says so explicitly: a warning in the log and baselineTruncated / baselineTruncatedTotal (this run / the whole life of the label) in the saved record and on the webhookUrl payload. If you see it, narrow the query (a country, a CPV code, a shorter publication-date window) or split it across several labels so each baseline stays under the cap. A baseline run also stops walking at 20,000 notice ids, and already warns separately when it hits that.

Why there's no snapshot-diff watchChanges here — and what to use instead

Some of our other Actors (grants.gov, openFDA recalls, USAspending, ClinicalTrials.gov, NIH RePORTER) offer a watchChanges input that re-delivers a record when a field on the same id mutates. TED doesn't work that way: we checked live before building anything, and TED never edits a published notice. A correction (deadline moved, specs revised, opening date pushed back) is published as a brand-new notice with its own publicationNumber — the original notice's own record never changes, so there is nothing for a snapshot diff to catch. (Confirmed on real examples: publication 493171-2026 was corrected twice, by 566391-2026 and 625075-2026, and 493171-2026 itself never mutated — three separate publication numbers, one shared procedureIdentifier.)

watchLabel already surfaces a corrigendum correctly, since it's a genuinely new publicationNumber your baseline hasn't seen. What's new in this version is changeReasonDescription — on a corrigendum notice, TED's own field explaining exactly what changed, e.g. "Deadline for receipt of tenders: INSTEAD OF 24/08/2026 PLEASE READ 10/09/2026" — and procedureIdentifier, a stable UUID shared by a notice and every corrigendum against it, so you can group them into one procurement thread instead of treating each as unrelated. Zero extra API calls: both fields ride along on the same page fetch every other field already uses.

Output

One row per notice:

FieldDescription
publicationNumberTED's own ID for the notice, e.g. 596425-2026.
noticeType, noticeSubtype, procedureTypeTED's notice-type code, subtype code, and procedure type (e.g. open, restricted).
title, titleLanguageNotice title in your chosen outputLanguage (or its fallback), and which language it actually came back in.
buyerName, buyerCountry, buyerCityThe contracting authority and its location.
buyerEmail, buyerPhone, buyerUrlThe buyer's own published contact details, when TED has them.
placeOfPerformanceCountry, placeOfPerformanceCityWhere the contract is performed (arrays, deduplicated — TED repeats these per lot).
contractNature, cpvCodese.g. ["services"], ["71000000"] (arrays, deduplicated).
descriptionFree-text lot description, in outputLanguage.
totalValue, totalValueCurrencyContract value, when the notice type carries one — see the FAQ.
deadlineDate, daysUntilDeadline, deadlineTypeEarliest submission deadline across all lots, how many whole days are left before it (negative = already closed, null = no deadline published), and which TED field the date came from: tender (the tender-receipt deadline — 48/50 live call-for-competition notices in a fresh measurement, see the deadline-fields guide), generic (1/50), or expressions (the expressions-of-interest deadline on two-stage procedures, 0/50). Result/award notices (can-standard) carry none of the three fields — 0/50 in the same measurement — which is why onlyOpenDeadlines treats "no deadline published" as closed.
deadlineReceiptRequestDateThe separate tender-documents/information-request deadline, where TED publishes one.
publicationDateWhen TED published the notice.
noticeUrlLink to the notice's PDF (or XML) on ted.europa.eu, in your chosen language when available. Kept for backward compatibility — prefer the three fields below for a specific format.
pdfUrl, htmlUrl, xmlUrlThe same notice as a downloadable PDF, a browsable HTML page, and machine-readable XML, each in your chosen language when available. null for a format TED doesn't publish for that notice.
procedureIdentifierA stable UUID shared by a notice and every corrigendum published against it — group them into one procurement thread.
changeReasonDescriptionTED's own plain-text explanation of what changed. Only present on corrigendum notices; null on an original notice.

Sample row (real output, German construction-engineering notice)

{
"publicationNumber": "596425-2026",
"noticeType": "cn-standard",
"procedureType": "restricted",
"title": "Germany – Architectural, construction, engineering and inspection services – BLB NRW Köln / Universität Bonn / Neubau Molekulare Biologie (ImBIG) / Bauphysik",
"titleLanguage": "eng",
"buyerName": "Bau- und Liegenschaftsbetrieb NRW Köln",
"buyerCountry": "DEU",
"buyerCity": "Köln",
"noticeSubtype": "16",
"buyerEmail": "BLBVergabe@blb.nrw.de",
"buyerPhone": "+49 0",
"buyerUrl": "http://www.blb.nrw.de",
"placeOfPerformanceCountry": ["DEU"],
"placeOfPerformanceCity": ["Bonn"],
"contractNature": ["services"],
"cpvCodes": ["71000000"],
"description": "Leistungen der Fachplanung Bauphysik (Wäreschutz, Raumakustik, Bauakustik)",
"totalValue": null,
"totalValueCurrency": null,
"deadlineDate": "2026-09-16",
"deadlineType": "generic",
"daysUntilDeadline": 12,
"deadlineReceiptRequestDate": "2026-09-29",
"publicationDate": "2026-08-31",
"noticeUrl": "https://ted.europa.eu/en/notice/596425-2026/pdf",
"pdfUrl": "https://ted.europa.eu/en/notice/596425-2026/pdf",
"htmlUrl": "https://ted.europa.eu/en/notice/-/detail/596425-2026",
"xmlUrl": "https://ted.europa.eu/en/notice/596425-2026/xml",
"procedureIdentifier": "8041f035-c752-48c6-8772-62de0a83aa8b",
"changeReasonDescription": null
}

totalValue is null here because this particular notice type doesn't carry one — see the FAQ. daysUntilDeadline is computed at run time (whole days, counted in Brussels local time — the zone TED itself stamps every deadline in), so the same notice returns a smaller number each day and goes negative once it closes. changeReasonDescription is null because this is an original notice, not a corrigendum; on a corrigendum it reads like "Deadline for receipt of tenders: INSTEAD OF 24/08/2026 16:00 +02:00 PLEASE READ 10/09/2026 16:00 +02:00".

Pricing

result — $0.0015 per returned notice (cut from $0.003 on 2026-10-02 — see below). The run start is free, no minimum spend.

Price cut 2026-10-02, from $0.003 to $0.0015 per notice. At $0.003 this Actor priced above five of the seven named rivals at ordinary run sizes with 2 users and $0 revenue on it — nothing to protect by holding price — while bin/store-rank shows the listing itself is not the problem: it lands top-10 on several TED-specific search terms a real buyer would type (european tenders p2, ted europa p2, cpv codes p2, tender data api p1, government tenders europe p7 of apify.com/store's live Algolia search, measured 2026-10-02). A findable listing with an uncompetitive price is a real lever to pull; an invisible one would not be. All rival prices below re-verified live 2026-10-02 at the new $0.0015 rate; where a rival uses Apify's tiered pricing we quote every tier that changes the comparison.

At $0.0015 we now beat every one of the following at every tier and every run size, not just on average: foxlabs/ted-tenders (46 users) charges $0.004/result + $0.00005 start — $1.50 vs. $4.00 per 1,000, 62.5% cheaper (was 25% before the cut). dltik/ted-europa-scraper (37 users, re-verified live 2026-10-16) charges $0.005/tender flat — $1.50 vs. $5.00 per 1,000, 70% cheaper (was 40%). artificially/eu-tenders-scraper (40 users, dormant) charges $0.003/item + $0.10 start at FREE and $0.0021/item + $0.07 start at GOLD+ — both tiers are now pricier than us on both the per-item rate and the start fee, so there is no longer a crossover where they overtake us (there used to be one, at ~78 notices). adobeflex/ted-lite charges $0.002/notice + $0.001/search + $0.00005 start — at $0.003/notice we lost from the second row onward; at $0.0015 our per-row rate is below their per-row rate alone, before even counting their search and start fees, so we win at every run size now, not just the first row. scrapers_lat/eu-ted-tenders-scraper (verified live 2026-10-05) charges a tiered result price from $0.0026 (FREE) down to $0.002 (GOLD and up) — correction to the 2026-10-02 audit's claim of a "$0.004–$0.001 start fee" on this listing: its live record has no apify-actor-start charge event at all, so the right comparison is $0.0015 flat against their $0.002 floor, and we beat it at every tier with no crossover, not "past 10 notices" as previously stated.

Two rivals still genuinely undercut us, with the arithmetic: memo23/ted-tenders-scraper (verified live 2026-10-05) charges a $0.005 start fee plus $0.001/notice, so it is cheaper than us on any run of 11 or more notices (crossover moved from 2.5 to 10 notices after the cut) and costs $1.005 per 1,000 against our $1.50. jungle_synthesizer/ted-eu-procurement-full-scraper charges a $0.10 start fee plus $0.001/record, cheaper than us only on batch runs of more than 200 records (was 50) — a run-fee-shaped price, not a per-query one. Both rivals' prices verified live 2026-10-02.

One rival is a genuine partial undercutter: publicmoney/ted-tender-scraper is tiered $0.002 FREE / $0.0015 BRONZE / $0.00125 SILVER / $0.001 GOLD / $0.00085 PLATINUM / $0.0007 DIAMOND, plus a $0.00005 start fee and a $0.01 minimum charge per run. At our new $0.0015 we now beat its FREE tier (0.0015 < 0.002), tie its BRONZE tier exactly, and lose from SILVER tier up — the opposite of the old picture, where we lost at every tier including FREE. Price verified live 2026-10-02.

One adjacent listing is far cheaper than all of the above and is not a TED scraper: maximedupre/eu-funding-tenders-scraper charges $0.00001 per opportunity, but it reads the EU Funding & Tenders Portal — the Commission's own grants and direct-procurement portal — not TED's Tenders Electronic Daily. It does not return member-state notices, so for TED coverage it is not a substitute at any price. Price verified 2026-10-02.

Correction, 2026-10-03: we are not the cheapest TED Actor on the Store, and the paragraphs above are not the whole picture. Every rival price above is still accurate and was re-verified live on 2026-10-03 with zero drift — but the seven-rival set they compare against came from a narrow Store sweep. A 12-term sweep run on 2026-10-03 surfaced 364 distinct listings, 186 of which mention TED or EU/European tenders or procurement, and pricing all 186 live found at least fourteen that undercut this Actor's $0.0015/notice, most of them never named here before (the first version of this paragraph said fifteen and counted westerly_breaker/ted-tender-monitor among them — that was a misreading of its charge events, corrected on 2026-10-03 and explained two paragraphs down). The honest bottom line is the one in the paragraph after next: price is not where this Actor wins.

The undercutters, with the arithmetic (all read live 2026-10-03). Cheaper than us at every run size: bikram07/eu-tenders-feed is on Apify's FREE pricing model — $0 per row at any volume; highbrow_qualification_z7w/eu-tenders-monitor charges $0.0001/row + $0.00005 start, 15x below us, though it is scoped to Germany/Austria/Switzerland only; getascraper/eu-ted-tender-monitor charges $0.00053 → $0.0004/row + $0.00005 start; thriftykiwi/eu-ted-tenders-scraper charges a flat $0.001/row with no start fee and no minimum, so it beats us on row 1 and every row after. Cheaper past a handful of rows: vhsgreed/eu-ted-tenders-api-fresh ($0.000045/row + $0.002 start) from ~2 rows; guyweitzman/eu-tenders-scraper ($0.0006/row + $0.002 start) from ~3 rows; rod_analytics/ted-tenders ($0.001/notice + $0.001 start) from ~3 rows; soilair/ted-eu-tenders-api, rigelbytes/eu-tenders-scraper and koalastuff/eu-ted-tender-monitor — all three at $0.001 → $0.0007/row + $0.00005 start — from ~1 row; 8tp/eu-ted-tender-lot-award-collector ($0.001/row + $0.00005 start, $0.002 minimum per run) from ~5 rows; deriverge/eu-tenders-scraper ($0.001 FREE → $0.0005 Diamond, $0.02 minimum per run) from ~14 rows on its Free tier and sooner above it; logiover/global-public-tenders-scraper (verified live 2026-10-05 — tiered $0.002 → $0.0014/row with a start fee at the same tiered rate) from ~14 rows on Gold and up, while on Free/Bronze/Silver we are still cheaper; and jungle_synthesizer/eu-national-procurement-portals-scraper (TED plus six national portals, $0.10 start + $0.001/record) past ~200 records, the same run-fee shape as its sibling named two paragraphs up. One more beats us only on a plan: steadydata/eu-tenders is tiered $0.002 Free → $0.0013 Gold and up with no start fee, so we win below Gold and lose from Gold up.

What the widened sweep also found that is not a price story (every listing and price in this paragraph verified live 2026-10-03). parseforge/ted-eu-procurement-scraper is the fifth-biggest listing in this niche and had never been named here — it is not an undercutter ($0.006 Free → $0.0055 Gold and up, about 4x our rate), but omitting a listing that size from a competitor comparison was an oversight, not a judgement. Also checked and dearer than us at every tier: alwaysprimedev/ted-eu-procurement-scraper ($0.0025 + $0.00005 start), nerdrx/german-tenders-monitor ($0.004 + $0.005 start, bund.de/DTVP/evergabe as well as TED), scrapepilot/gov-tenders-scraper-usaspending-ted-uk-contracts ($0.002 + $0.02 start), parseforge/ted-europa-tenders-scraper ($0.004/notice + $0.02 start plus eleven per-section add-on events), ikoles/eu-ted-tender-deadline-radar ($0.004 + $0.00005 start — a deadline-focused product like our onlyOpenDeadlines/minDaysUntilDeadline, at nearly 3x the price), straightforward_hydra/eu-ted-tender-intelligence and alex_r_ai/ted-eu-tenders-scraper ($0.005 each), siccscha/ted-tender-scraper ($0.004, no start fee), pappy-dev/eu-ted-procurement ($0.002, no start fee), euroscrape/eu-public-tenders ($0.003 → $0.0021 + $0.003 start), mtellez23/eu-public-tenders-scraper ($0.005), fuyuki0/government-tender-scraper ($0.004), nexgendata/eu-ted-tender-monitor ($0.1/record), omarchydev/eu-tender-data ($0.1/lot), and parseforge/european-ted-tenders-scraper ($0.021/row — the dearest TED listing found). One more, adjacent rather than head-on: lofomachines/public-tenders-scraper (74 users, 5 new in 30 days) is the biggest listing anywhere in this broadened sweep, but it is a multi-country aggregator over Italy, France, Germany, Spain, the UK, the US and India rather than a TED reader — it does not give you TED's own notice numbers, CPV subtree behaviour or notice/procedure-type codes — and at $0.004 → $0.0028/row + $0.00005 start it is dearer than us at every tier. Verified live 2026-10-03. Correction, 2026-10-03 — one listing moved from the cheapest column to the dearest. An earlier version of the paragraph above named westerly_breaker/ted-tender-monitor as the niche's second-cheapest listing at "$0.00001/row + $0.00005 start, ~150x below our rate." That was wrong. Its live pricing record carries three charge events, and the platform's isPrimaryEvent flag sits on a vestigial apify-default-dataset-item priced at $0.00001 — but the Actor's own README pricing table documents exactly one charged event, tender-result at $0.005 once per returned tender, with worked examples ("20 matching tenders → 20 × $0.005 = $0.10"). Its pricing history shows why the record is misleading: the owner listed it on 2026-07-06 with tender-result flagged primary and moved the flag to the dataset-item event 53 minutes later, leaving the $0.005 event live and chargeable. So the right comparison is $0.005/notice against our $0.0015 — it is roughly 3.3x dearer than us at every run size, not cheaper, which also makes it one of the dearest TED listings in this niche rather than the second-cheapest. Read live and cross-checked against its own published pricing table on 2026-10-03. The general lesson, which applies to every price comparison on this page: a rival's isPrimaryEvent flag is a Store-page display hint, not a statement about what its code actually charges, and where the two disagree we go with the rival's own documented pricing table.

A structural note worth more than any single handle: the niche is being flooded. Of the undercutters above, every one priced its current rate between 2026-07-06 and 2026-09-29, and all of them have 1–2 users. New entrants are arriving faster than any of them is gaining customers, and they are arriving cheap.

Eighth sweep, 2026-10-04 — three more undercutters, and a correction to where we were looking for them. A fresh 12-term sweep surfaced 366 listings, 232 of them matching this niche, and diffed the full matched set (not just the top listings) against every handle named on this page: 190 had never been named here. Our own live price was re-read directly off the platform first and is confirmed flat $0.0015/result with no start fee at every plan, so every comparison below is against that number and not against an intended one. The sweep's own structure is the first finding: every unnamed listing with 3 or more users is a national-portal scraper, not a TED reader — jungle_synthesizer/bidnetdirect-government-bids-scraper (25 users, US BidNet Direct), scrapers_lat/seace-scraper (Peru), inexhaustible_glass/german-tender-scraper, rastriq/placsp-scraper (Spain), lexis-solutions/evergabe-scraper (Germany), publicmoney/tenderned-scraper (Netherlands), apexforge/italian-public-tenders-monitor, publicdata/uk-contracts-finder-find-a-tender (UK) and the rest read their own country's procurement site, which publishes below-threshold notices TED never carries and omits the cross-border notices TED exists for. They are complements, not substitutes, at any price. The real TED-native competition in this niche all sits at 1–2 users — so ranking a sweep by user count, which is what every audit on this page before this one did, sorts by listing age and systematically looks away from the listings that actually price against us. All prices below read live from each Actor's own pricingInfos record on 2026-10-04.

Cheaper than us at every tier and from the first row: chorelet/government-tenders-scraper (EU TED + UK + SAM.gov in one Actor) charges a tiered tender event from $0.001 (Free) down to $0.0007 (Gold and up) on a $0.00005 start fee — below our $0.0015 at every plan with no crossover. Its optional detail event ($0.002 → $0.0014) is charged on top if you pull full notice detail, so a detail-heavy run can land dearer than us; a plain notice list does not. Cheaper from a handful of rows, on the upper plans only: perceptr0n/eu-tenders-ted-scraper is tiered $0.002 Free / $0.0015 Bronze / $0.0012 Silver / $0.001 Gold / $0.0007 Platinum / $0.0005 Diamond plus a $0.01 flat start fee — we win outright on Free, and on Bronze its row rate ties ours exactly so its start fee decides it our way, but from Silver up it overtakes us past roughly 34 notices per run (Silver), 21 (Gold), 13 (Platinum) and 11 (Diamond). automation-lab/eu-ted-procurement-notices is tiered $0.0023 → $0.0012 on a $0.005 start fee: dearer than us on Free, Bronze and Silver at any size, and cheaper only on Gold and up past ~17 notices per run. One more undercuts us on shape rather than rate: icekurt/ai-tender-rfq-opportunity-radar carries no per-result charge at all — a single $0.05 flat Actor-start event — so it is a per-run price that beats our per-row one on any run returning more than about 34 notices, and loses on anything smaller.

Checked in the same sweep and not undercutters, listed so the next audit does not re-price them: eiv/tender-scraper advertises $0.0012/tender, below our rate, but bills $0.005 at start plus $0.008 per source searched and $0.004 per contact found, so on a single source it only overtakes us past roughly 43,000 tenders in one run. Dearer than us at every tier and run size: metsuryu/ted-eu-tenders-scraper (flat $0.00175), datadelta/ted-tender-change-monitor, kobakotools/pubdata-sam-ted-tenders, mochiboo/eu-tenders-ted-scraper and fetchwerk/eu-tenders-scraper (flat $0.002 each), xerophylous_mercy_0wn/eu-tender-radar and nicolas_izquierdo/eu-tenders-monitor ($0.0025), knotty_mistveil/ted-eu-tenders, nordicdataforge/eu-tender-contract-award-monitor, promptica/ted-gare-eu and publicrecords/eu-ted-notices-scraper ($0.003 → $0.0021), captainhandsome/ted-eu-tender-search ($0.003 → $0.0021 plus a tiered start fee), agentready/eu-tenders-ted ($0.0035 → $0.0028), neuton/eu-ted-procurement-notices-scraper, antishock/ted-eu-tenders-procurement-scraper and grilled_gorge/eu-ted-tender-scraper ($0.004), automation_studio/eu-tender-procurement-scraper ($0.005 → $0.003 with a $0.10 run minimum), codeclouds/nl-eu-tenders-scraper, nefes-tools/eu-tenders, newsignal/ted-delta-monitor and uplifted_novice_vbl/ted-tender-watch ($0.005), scrapesage/global-tenders-scraper ($0.008 → $0.002), apeye/government-tenders-api ($0.008), moving_beacon-owner1/ted-eu-tenders-scraper and scrapemint/government-tender-finder ($0.01), publicdata/ted-tenders-eu-procurement ($0.005 → $0.003 charged on both its start and its notice event) and dalbian/public-tender-monitor ($0.15 per search plus $0.01 per notice — the dearest TED listing found in any sweep on this page). One scope note: automation-lab/tenderned-netherlands-tenders-scraper prices its rows at $0.000041 down to $0.00001 — far below anything else named here, and below our rate by two orders of magnitude — but it reads TenderNed, the Dutch national portal, not TED, so like maximedupre above it is not a TED substitute at any price.

Ninth sweep, 2026-10-05 — applying the fleet's full-cohort rule, no listing ruled out by title alone. A fresh sweep found 236 matched listings (up from 232 the day before — this niche adds new entrants daily). Own price re-verified live first: unchanged flat $0.0015/result, no start fee, zero drift from meta.json. Every one of the 27 unnamed listings with 3 or more users was read off its own live description, not its title, confirming the 2026-10-04 finding still holds with a fresh set of specific handles: all 27 are national/regional-portal scrapers (India GeM jungle_synthesizer/gem-india-government-emarketplace-bids-scraper, Kenya, India CPPP, France BOAMP x2, Germany, UK Find a Tender, Morocco, Romania SEAP/SICAP — whose own description states "not in EU TED" — Norway DOFFIN, France DECP, Spain PLACE/PLACSP x2, UK Contracts Finder, Croatia EOJN, Brazil PNCP x2, Italy ANAC, Scotland, Poland eZamowienia, Finland Hilma, Austria, Czech NEN, Peru OECE, Mexico Nuevo Leon), none mentioning TED anywhere in their live description. Below that floor, the 1–2-user tail grew by 47 newly-unnamed TED-native/multi-country listings since the 2026-10-04 sweep — all 47 were live-priced via GET /v2/acts/<owner>~<slug> rather than skimmed by title. Two are genuine new undercutters: om_kh/eu-tenders-scraper is tiered $0.0015 (Free) → $0.000825 (Gold+), no start fee — ties us at Free and undercuts at every paid tier, with no crossover in our favor; maydit/eu-tenders-scraper is tiered $0.002 (Free/Bronze) → $0.0016 (Silver) → $0.0012 (Gold+) plus a $0.00005 start fee — dearer than us through Silver, cheaper from Gold up. Two more tie our flat rate exactly with no crossover either way: kadi_bence/ted-tenders-scraper ($0.0015/notice flat) and piotrv1001/ted-eu-tenders-scraper ($0.0015/notice-basic, before any lot-level add-on events). The remaining 43 are dearer than us at every tier checked, ranging $0.002–$0.1/row (several are enrichment/alert/AI-scoring products billing a materially higher per-row rate for that reason, e.g. garonne/eu-tender-screen $0.05/screened-tender, jdepablos/eu-tender-watch $0.1/match, intimate_pacu/ted-buyer-history-enrichment-api $0.05/row) — not individually quoted here for space; this paragraph is the record that they were checked and ruled out on price. The structural picture from 2026-10-04 is confirmed, not changed: the niche keeps adding 1–2-user TED-native entrants daily, most pricing at or above our rate, with the occasional one landing a notch under us at the top tier.

Tenth sweep, 2026-10-06 (cycle 1305). Re-ran the unnamed-cohort cut: 374 seen, 241 matched (up from 236), README names 96 handles. The >=3-user unnamed cohort is now 26 listings (down from 27, composition changed) and every one was read off its own live description, not its title — the pattern holds exactly: all 26 are single-country/regional-portal scrapers, none mentioning TED. New since the ninth sweep: a vendor called publicmoney has launched ten of them in this cut alone (UK Find a Tender, France BOAMP, France DECP, Spain PLACE, Croatia EOJN, Poland e-Zamowienia, Scotland, Czech NEN, Peru OECE, Mexico Nuevo Leon — each confirmed single-portal by its own live description), plus alpinedata/german-public-tenders (Germany), wafspaul/kenya-government-tenders, and others already the same shape. None is a TED substitute at any price, so no README price claim changes. Not re-run this cycle, for time: the 1-2-user TED-native tail (the part of the cohort that actually produces undercutters, per the ninth sweep) — that full re-sweep is the next competitor_audit touch on this Actor if one lands here again soon; this cycle only re-confirmed the scope exclusion at the >=3-user floor. Re-verified live 2026-10-06 (cycle 1334): spot-checked alpinedata/german-public-tenders (still Germany-only per its own live description, flat $0.002/row) and wafspaul/kenya-government-tenders (still Kenya-only, flat $0.002/row) — both unchanged and still correctly excluded as non-TED.

Eleventh sweep, 2026-10-07 (cycle 1348) — the 1–2-user tail sweep the tenth sweep deferred, and three new undercutters. Own price re-read off the platform first: unchanged flat $0.0015/result, no start fee, no minimum, zero drift. This sweep closes the gap the tenth sweep left open: 241 matched listings, 151 of them never named on this page, and all 151 live-priced end to end — the entire 1–2-user floor included, not just the ≥3-user cut. Every one is on Apify's PAY_PER_EVENT model; none is on the FREE model, so the bikram07 $0-per-row entry cited below is still the only free TED-native listing found in any sweep here. Nine of the 151 price under our $0.0015/notice, and six of those nine are out of scope on their own live descriptions, not their titles — two Brazil PNCP readers (latinamericadata/pncp-brasil, aryrabelo/pncp-procurement-scraper), two Austrian USP readers (publicdataworks/austrian-public-tenders-scraper, publicdataworks/austria-contract-awards-scraper), a Dutch TenderNed reader (nocodeventure/tenderned-scraper), and adobeflex/cpv-naics-mapper, which maps CPV codes to NAICS and back and returns no notices at all, so it is not a substitute at any price. The three that survive are genuine, and none had ever been named here. Cheaper than us at every run size: thriftykiwi/public-tenders-aggregator charges a flat $0.001/result with no start fee and no minimum, so it beats us on row 1 and every row after — note this is a second listing from the same owner as thriftykiwi/eu-ted-tenders-scraper named above, on exactly the same price shape, and it reads EU TED, UK Contracts Finder and AusTender in one keyword search. Cheaper past a handful of rows: mrprince90/tender-opportunity-matcher charges $0.00002/row plus a $0.005 one-time start fee, so it overtakes us from about 4 rows up and costs $0.025 against our $1.50 per 1,000 — that per-row rate is the lowest of any listing that reads TED found in any sweep on this page, and it is a multi-portal matcher (Indonesia LPSE, TED EU and other global portals) with business-profile scoring rather than a dedicated TED reader. And ilborso/eu-tenders-procurement-opportunity-notification, whose own description says it "automatically search[es] TED (Tenders Electronic Daily)", charges $0.00049/result plus a $0.02 start fee, so we are cheaper below 20 notices and it is cheaper from about 20 up — $0.51 against our $1.50 per 1,000 — with the crossover moving out to roughly 70 notices if its optional $0.05 email-delivery event fires. All three read live 2026-10-07. Two records in this tail were genuinely ambiguous and were resolved by hand rather than guessed at: oldjard/uk-eu-public-tenders and datalantern/government-tenders each carry two charge events with isPrimaryEvent set on neither, so no automatic rule can pick the comparable unit; reading each listing's own events (apify-actor-start/actor-start is the run fee, tender-found/notice is the per-row unit) puts both at $0.003/row, twice our rate — oldjard's own description states "$3 per 1,000 notices," which confirms the reading — and datalantern reads the UK, Australia and Canada rather than TED in any case. One forward-dated price, forecast landed and re-verified live 2026-10-16: boubap/ted-tenders-scraper is TED-native and was $0.002/notice (dearer than us); its scheduled increase to $0.0035/notice effective 2026-10-10 is now in effect, moving further above us rather than under — still no threat. Standing lesson confirmed again: every price check in this fleet filters to startedAt <= now, so a dated future entry is invisible unless a sweep reads for it specifically. The remaining 142 listings price at or above our rate and are the record that they were checked and ruled out. The structural picture from the eighth and ninth sweeps is confirmed once more: this niche adds 1–2-user entrants daily, the ≥3-user band is almost entirely national-portal scrapers that are complements rather than substitutes, and the listings that actually price against us keep arriving at the very bottom of the user-count distribution — so any future audit here that ranks by users and stops at a top-N cut will miss them by construction.

Twelfth sweep, 2026-10-08 (cycle 1411) — closing the eleventh sweep's own blind spot. The eleventh sweep's batch pricer read only flat per-event prices; any of its 151 listings using Apify's tiered eventTieredPricingUsd shape came back with an empty tier table and could not have been found to undercut us whatever its real price was — filed as 0-TODO-h1396-ted-invisible-60. Repointed that script at the fleet's shared tier-aware pricer and re-priced live the exact 60 listings the old file recorded with empty tiers. Own price re-verified live first: unchanged flat $0.0015/result, no start fee.

One is a genuine, previously-invisible undercutter at every tier and every run size: deriverge/public-tenders-scraper (2 users), whose own description names TED plus the UK's Find a Tender and Contracts Finder as its three sources, is tiered $0.001 (Free) down to $0.0005 (Gold and up) with no start fee — cheaper than our $0.0015 from row 1 at every plan, with no crossover in our favor. One more is a genuine partial undercutter: humble-echidna/eu-ted-tenders (1 user, TED + UK Find a Tender) is tiered $0.002 (Free) → $0.0018 (Bronze) → $0.0016 (Silver) → $0.0014 (Gold and up) — dearer than us through Silver, cheaper from Gold up. andok/eu-tenders-scraper (3 users, TED-native) is tiered $0.01 (Free) down to $0.0014 (Diamond) plus a $0.0028 start fee — dearer than us at every tier except Diamond, and even there the start fee pushes its crossover out to roughly 28 notices per run, so it is recorded but not a material threat.

Five of the 60 are single-country portals, not TED, and stay out of scope for the same reason as every other national-portal exclusion on this page: two Jungle Synthesizer listings (Morocco marchespublics-morocco-public-tenders-scraper, Chile mercadopublico-chile-public-procurement-scraper), deriverge/uk-tenders-scraper (Find a Tender + Contracts Finder only, no TED despite the similar name to the genuine undercutter above), and the ten publicmoney/* single-portal listings already excluded in the tenth sweep. The remaining listings in this 60 price at or above our rate and are the record that they were checked and ruled out.

Thirteenth sweep, 2026-10-16 (cycle 1804) — the ≥3-user unnamed tail, re-priced live. 1,417 Store listings seen across the search terms, 417 niche matches, 118 named handles, 306 unnamed; the 53 of those that clear the 3-user floor were live-priced end to end through the same tier-aware pricer. Own price re-read off the platform first: unchanged flat $0.0015/result, no start fee, no minimum, zero drift. Twenty-one of the 53 carry a tier under our $0.0015, and not one of them is a TED reader — the structural picture from the tenth through twelfth sweeps holds exactly, and this is now the fourth consecutive sweep in which every ≥3-user undercutter turned out to be a national-portal scraper rather than a TED substitute. Thirteen of the 21 are a single owner's catalogue: publicmoney/* has now grown to thirteen listings in this cut (BOAMP France, India CPPP, Poland e-Zamowienia, Morocco Marchés Publics, UK Find a Tender, Croatia EOJN, Mexico Nuevo León, Spain PLACE, France DECP, Peru OECE, Ukraine Prozorro, Czech NEN, Public Contracts Scotland — up from ten at the tenth sweep), every one on the identical ladder of $0.002 Free → $0.0015 Bronze → $0.00125 Silver → $0.001 Gold → $0.00085 Platinum → $0.0007 Diamond plus a $0.00005 start fee, so each is dearer than us on Free, ties us exactly on Bronze, and undercuts us from Silver up — but each reads exactly one national portal, so none is a substitute for TED at any tier. The deepest per-row undercuts in the cohort are also national-portal-only: automation_craft/uk-find-a-tender-scraper (1 users) at $0.0005 → $0.0004 plus a $0.002 start fee and jungle_synthesizer/ukraine-usr-reconstruction-contracts-scraper (3 users) at $0.0005 → $0.0004 with no start fee are both roughly 3–4x under our row rate; eloquent_mountain/tenderned-publications-scraper (5 users, Dutch TenderNed) is on Apify's FREE model at $0 per row, the only free listing in this cut; anchor/apify-actor-ugap (3 users, the French UGAP catalogue) and rastriq/boe-scraper (3 users, Spain's Boletín Oficial del Estado) are $0.001 flat; jungle_synthesizer/marchespublics-morocco-public-tenders-scraper (5 users) is $0.001 → $0.0006 but behind a $0.10 start fee, so its start fee alone costs what 67 of our notices do and we are cheaper on any run under ~100 records; and studio-amba/ezamowienia-scraper (1 user, re-verified 2026-10-18, Poland) is $0.002 → $0.0012 behind a $0.005 start fee. Every genuinely TED-native listing in the ≥3-user cohort is dearer than us, by a wide margin — re-read live this sweep: ponderable_hydrometer/ted-tenders-scraper $0.005/notice (3.3x us), gazidev/global-tender-alerts $0.005 (TED plus UK, Canada and SAM.gov), baptsg/eu-public-tenders-scraper $0.006 (TED plus national bulletins, 4x us), lindenwerk/german-eu-tender-matcher $0.01 (6.7x us), and the largest unnamed listing anywhere in this sweep, ciel_labs/uk-government-tenders-contracts-finder (17 users, 12 of them new in the last 30 days — the fastest-growing listing in the niche), at $0.008/notice with no start fee, over 5x our rate, and UK-only in any case. Pricing decision: holding flat at $0.0015. Nothing in this cohort changes the arithmetic the 2026-10-02 cut was based on: no TED reader has moved under us, and the sub-$0.0015 listings are complements that a TED buyer would have to run in addition to us, not instead of us. Three forward-dated pricing entries were read for explicitly, since every automated check in this fleet filters to startedAt <= now and is blind to them: bstandco/france-public-tenders and studio-amba/boamp-scraper each move onto Apify's FREE model (2026-10-22 and 2026-10-27 respectively) and bgfc97/government-tenders switches to PAY_PER_EVENT on 2026-10-22 — all three are national-portal or multi-country aggregators rather than TED readers, so none changes a claim on this page, but the two FREE flips are worth re-reading after those dates. The remaining 32 of the 53 price at or above our rate and are the record that they were checked and ruled out.

So the bottom line after this audit is: we are not the cheapest EU TED Actor at any run size, and we do not intend to compete on price here. The 2026-10-02 cut from $0.003 to $0.0015 was decided against the seven-rival view in the paragraphs above; the real distribution has a TED-native rival at $0 per row (bikram07/eu-tenders-feed, on Apify's FREE model) the cheapest dedicated TED reader below that at $0.000045 per row (vhsgreed/eu-ted-tenders-api-fresh, ~33x below us), and — found in the eleventh sweep above — a multi-portal tool that reads TED among others at $0.00002 per row (mrprince90/tender-opportunity-matcher, ~75x below us, behind a $0.005 start fee), so there is no price that wins this niche and we are not going to chase it. (This sentence previously cited "$0.00001 per row" as the floor; that came from the westerly_breaker misreading corrected above — the $0.00001/opportunity listing that is real, maximedupre, reads a different portal and is not a TED substitute, so it does not belong in a TED price floor.) What we ask you to weigh instead is the filter and output work described in the next paragraph and the FAQ — the documented TED CPV-subtree behaviour, the complete 22-notice-type and 18-procedure-type dropdowns (exhausted against TED's own index, including the two plausible-looking codes TED rejects with HTTP 400), the measured field-fill rates, deadline filtering against a computed daysUntilDeadline, watch-mode alerts with a tracked baseline, and the duplicate-row guard that stops TED's own paging from charging you twice for one notice. None of the cheaper listings above documents any of that on its Store page, checked 2026-10-03; we have not audited their input schemas field by field, so that is a statement about their published pages, not about their code.

On features, read this comparison carefully, because an earlier version of this paragraph overstated it. foxlabs does ship keyword search over notice text and the same 24 output languages we do, and its "expert query" field accepts TED's native DSL, which can express a contract-value floor (total-value>=1000000) — so we do not beat them on full-text search, language coverage, or value filtering as such. What this Actor adds over their live input schema: procedureType filtering (their noticeTypes filters the notice kind — contract notice, award, corrigendum — not the procurement procedure), deadline-based filtering via onlyOpenDeadlines/minDaysUntilDeadline against the computed daysUntilDeadline, and watch-mode alerts with watchLabel/webhookUrl. The structural difference on value: their DSL documents that an expert query overrides every other filter, so there you pick either a value floor or your country/CPV/date filters, while minValue/maxValue here compose with everything else in the same run. Verified against their live input schema 2026-10-01.

What we do not claim on features. We have not audited the input schemas of the rivals named above field by field, so treat the feature comparison in this section as specific to foxlabs and nothing more. memo23/ted-tenders-scraper, the one with a real price advantage at volume, advertises CPV-code, country, notice-type, keyword and date filtering — the same core filter set we offer — so if price is your deciding factor and you do not need procedureType, deadline filtering, watchLabel/webhookUrl alerts or our output normalization, it is the cheaper way to get TED rows. Their advertised filter set was read off their live Store listing, checked 2026-10-02.

2026-10-07 cleanup: dropped every sub-20-user rival count from this README per the standing rule (an exact count is only published at 20+ users, since totalUsers churns in both directions and a one-user tick under 20 is automatically STALE at the checker's 10% tolerance) — 57 bare counts removed across the eleven sweeps above, every price claim, scope exclusion and feature comparison left intact. Twelve of the 57 were decorated in shapes a plain (N users) grep misses and were caught by reading the paragraphs: bare numbers standing in for counts in the eighth sweep's national-portal list ((13, Peru), (9, Spain)), the (…) short form, a 3-6 users range and two still N users re-verification notes. logiover/global-public-tenders-scraper's "2 new in 30 days" growth decoration went with its user count for the same reason; lofomachines's is left in place because that listing's count is above the threshold. Claims that were premised on a count were reworded rather than left dangling, not deleted: parseforge/ted-eu-procurement-scraper still reads as "the fifth-biggest listing in this niche," and maximedupre's paragraph now says its price was verified on 2026-10-02 rather than its price and user count. Counts at 20 and above are untouched (lofomachines 74, artificially 40, foxlabs 39, dltik 32, jungle_synthesizer/bidnetdirect-government-bids-scraper 22), as are the sweeps' structural cohort statements about where the TED-native competition sits (the "1–2 users" and ">=3-user" bands), which are dated findings rather than per-listing claims. No live re-check was needed for this edit: it only removes numbers, it doesn't restate any.

Thirteenth sweep, 2026-10-09 (cycle 1446) — regular rotation resweep, ≥3-user cohort only. Own price re-verified live first: unchanged flat $0.0015/result, no start fee (check-own-price-freshness 24/0). A fresh 12-term sweep found 380 seen / 247 matched (stable vs 246 at the twelfth sweep), README now names 114 full handles going in, leaving 143 unnamed (119 never-mentioned, 24 owner-mentioned-elsewhere). Live-priced the ≥3-user cohort, 23 listings, via the fleet's tier-aware pricer. The pattern every prior sweep found holds exactly: every one of the 23 is either a single-country/regional portal (Romania SEAP/SICAP, Norway DOFFIN, UK x2, France BOAMP, Spain x1, Czech NEN, Finland Hilma, India CPPP, Morocco, France DECP, Poland e-Zamowienia, Croatia EOJN, Argentina, Scotland, Peru, Mexico — several from the same publicmoney/* vendor family already excluded above, confirmed unchanged by live description, not title) or a listing already checked and found dearer at the twelfth sweep or earlier (redfoxxie/official-eu-public-tenders-monitor, still flat $0.004/result; datapilot/public-procurement-intelligence-hub, still a USASpending.gov reader with no TED/EU content, a false match on the generic word "procurement"). 0 of the 23 are genuine new undercutters. Several of the single-country listings (notably the publicmoney/tender-scraper family and studio-amba/nen-nipez-cz-scraper) do undercut our per-row rate from Silver tier up on the arithmetic alone, but — per the standing cycle-1228/1260/1261/1305/1387 scope ruling — a single-country portal is a complement to TED, not a substitute, so it is not disclosure-worthy regardless of price. No README price claim changes. Fleet-wide check-price-superiority (which checks every tiered rung, not just FREE) corroborates: 0 undisclosed on this file.

FAQ

Why not just call the TED API myself? You can — it's free and public. What you get here is normalization: TED's raw fields are multilingual maps and duplicated per-lot arrays, which are painful to consume directly. This Actor gives you one flat row per notice with an English-preferred title, a deduplicated CPV list and a single deadline date.

Does this cover contract value? Yes, when TED has it (totalValue/totalValueCurrency) — not every notice type carries a value (e.g. prior-information notices often don't). Use minValue/maxValue to filter on it directly instead of filtering the output yourself; notices with no value are dropped whenever either is set.

Which notice-type and procedure-type codes actually exist? All of them are in the two dropdowns — we exhausted TED's own search index to get the complete lists rather than documenting a handful of examples: 22 notice types (excluding all 22 leaves exactly 0 notices across TED's entire history) and 18 procedure types (8 modern eForms codes, 9 legacy pre-2023 single-character codes, plus comp-tend, TED still accepts). Two upstream traps this closes: there is no pin-standard code (prior-information notices are split across six pin-* codes) and no exp-int-rest procedure type — both are plausible-looking values TED rejects outright with HTTP 400, which used to fail the run with a misleading "TED outage, please re-run" message. One asymmetry remains and it is TED's, not ours: the value 7 appears in the output procedureType field on some older notices, but TED's expert search refuses 7 as a filter value, so it is not selectable.

Correction, cycle 1533 (2026-10-11) — the "17 procedure types" count above was wrong. The original cycle-836 exhaustion missed comp-tend ("Competitive tendering", Regulation 1370/2007 art. 5(3) — a procedure specific to public passenger transport service contracts). Re-running the exhaustion live (NOT (procedure-type=<every known code>)) found a 198,118-notice residual instead of the expected near-zero; sampling it showed it was overwhelmingly notices with no procedure type at all (pre-2014, expected) plus the already-documented 7 quirk — except for comp-tend, which has 3,084 live matching notices spanning cn-standard, can-standard, pin-cfc-standard and pin-tran, confirmed independent of notice type. Re-running the same exhaustion with comp-tend added left only the None/7 residual, closing the set at 18. Added to the dropdown; nothing else in this niche's filters was affected.

Can I filter by procedure type (open vs. restricted vs. negotiated)? Yes — set procedureType to any TED procedure-type codes (e.g. open, restricted, neg-w-call). It's a server-side filter sent straight to TED alongside noticeTypes/cpvCodes/countries, so it doesn't cost extra requests. About 90% of notices carry this field in a recent live sample; the rest have no procedure-type recorded by TED and are excluded from any procedureType match the same way an unset value would exclude them from any other filter.

Can I search full text? Yes — set keywords (e.g. "cloud hosting"), which is sent as TED's FT~ full-text operator. It searches the whole notice text TED indexes, not just title/description/buyer name — verified live (2026-09-28): a search for "software" matched a German architectural-services notice whose only occurrence of the word was buried in its technical-capacity/selection-criteria requirements ("Angaben zur eingesetzten CAD- und AVA-Software"), a section this Actor doesn't expose as its own output field. So a returned row is a genuine match, but you may not be able to see why it matched by reading the output alone. For anything beyond that, expertQuery gives raw access to TED's expert-search syntax.

Can I pull a specific historical month or quarter, not just "the last N days"? Yes — set publicationDateFrom/publicationDateTo (either or both) to an absolute YYYYMMDD window; it overrides publishedWithinDays.

Can I get titles/descriptions in a language other than English? Yes — set outputLanguage to any of 24 EU language codes (e.g. deu, fra, spa, pol). TED publishes every notice in every EU language, so this returns the same notice in your chosen language instead of English, including a matching-language notice URL. Notices without a translation into that language fall back to English automatically.

How do multiple filters combine — AND or OR? Values within the same field are OR'd (countries: ["DEU", "FRA"] matches either), and different fields are AND'd (country + CPV code together narrows, doesn't widen). Set expertQuery if you need anything more precise than that — it replaces all the filters above with TED's own raw expert-search syntax.

Is buyerEmail/buyerPhone a personal contact? No — these are the contracting authority's own published contact point for the procedure (organisation-email-buyer/organisation-tel-buyer in TED's schema), republished verbatim from an official EU government source. Most are role mailboxes (vergabestelle@…, einkauf@…); we don't enrich or cross-reference them.

Why did my first watchLabel run return nothing? By design — the first run on a new label + filter combination is a baseline: it records everything currently matching so the next run can tell you what's new, and charges nothing.

I got 0 notices and the run still says "Succeeded" — what happened? A run that delivers nothing always says why in its status message, and you are charged nothing in either case. (1) A watched query found nothing new — every matching notice had already been delivered on an earlier run of that watchLabel; this is the expected result most of the time and nothing to fix. (2) Nothing matched your query at all, or matched but was dropped by minValue/maxValue/onlyOpenDeadlines/minDaysUntilDeadline after fetching — the message names whichever of those filters actually dropped a result, and otherwise suggests widening publishedWithinDays/publicationDateFrom/publicationDateTo, dropping a filter, or checking cpvCodes. Before cycle 1755 the watch-mode case (1) only logged a warning and left the Console's status message blank on an otherwise healthy run.

I set watchLabel and a fixed publicationDateTo — why has my watch stopped finding anything new? Because the two don't mix. publicationDateTo is sent to TED as an upper bound (publication-date<=...) on the exact field that decides whether a notice is new enough to exist yet. Live-measured 2026-10-11: publication-date<=20250901 matches only notices dated 2016 or earlier, while the real unbounded feed had notices dated as recently as 2026-10-08 — so once today's date passes your fixed cutoff, the query can never match a notice published after it, ever again. This run logs a warning naming the cutoff when it detects the combination. Drop publicationDateTo from a watched query (publicationDateFrom alone is fine) or drop watchLabel if you actually want a one-off historical window instead of an ongoing alert.

Can I reset or inspect a watch baseline? Yes. It is a plain JSON record in the fetchsmith-ted-watch key-value store on your own account, keyed by your label plus a fingerprint of your filters. Delete the record to start over, or read seenIds to see exactly what has been delivered.

A tender I'm tracking got its deadline extended — will watchLabel catch that? Yes, but as a new row, not an edited one: TED publishes the extension as a corrigendum with its own publicationNumber, so on your next watch run it arrives as a genuinely new notice. Match it back to the original via procedureIdentifier (both share it), and read changeReasonDescription for TED's own explanation of exactly what changed — no need to diff the two rows yourself.

Why do my results carry CPV codes I never asked for — and sometimes not the one I did? Because TED's classification-cpv filter matches the whole CPV subtree beneath the code you supply, at every level of the hierarchy, and a notice is usually tagged with several codes. There is no exact-code mode in TED's API, so there isn't one here either. Measured live on 2026-09-21 (publication window 2025-03-01..2025-03-31, 10 notices each): cpvCodes: ["72000000"] returned 10/10 notices carrying at least one 72… code but only 5/10 carrying the literal 72000000 (the rest were tagged 72313000, 72220000, 72200000, 72262000); cpvCodes: ["72220000"] returned only 5/10 with the literal code (others: 72222100, 72222300, 72224000); and even the narrow-looking cpvCodes: ["72267000"] returned only 6/10 with the literal code, because its children 72267100/72267200 match too. Picking a longer code narrows the subtree but never collapses it to a single code — a code only matches exactly when the CPV hierarchy gives it no children at all, and you can't tell which those are from the code alone. Workaround: filter the cpvCodes output array yourself after the run (e.g. keep rows where cpvCodes contains your exact code), or use expertQuery if you need TED's raw syntax.

Can the same notice be returned — and charged — twice in one run? No. TED is paged by page number over a live index and its search endpoint takes no sort parameter, so a notice published while a walk is in progress shifts later rows onto a page that was already read, and TED then serves the same publication-number on two pages. Every repeat is dropped before it is normalized, pushed or charged, so you pay for each notice exactly once; the run log names the count when it happens (N notice(s) were served more than once by TED's own paging) and the webhookUrl payload carries it as duplicateRowsDropped. Measured live on 2026-09-22 — 2,000 rows over 8 pages of a 4,486-match query, 0 repeats — so on short walks this is rare; the guard exists because the rate depends on how busy TED is while your run is walking, and a silent double charge is not something you should have to audit for yourself.

I'm exporting to Excel/CSV and the CPV codes column looks broken. That's Apify's default array export splitting cpvCodes (and the 3 other array fields) into numbered columns like cpvCodes/0, cpvCodes/1 that shift position between rows with different counts. Set flatten: true and re-run — those 4 fields become a single comma-separated string column instead.

Why are deadlineReceiptRequestDate/changeReasonDescription null on most rows? Both are gated by notice type, not a bug or a filter you're missing. Measured directly against TED's own API (250-notice live sample, last 30 days, all countries): deadline-receipt-request-date-lot fills on 8.3% of cn-standard (open contract notices — TED lets a buyer publish a separate request-to-participate deadline distinct from the tender deadline, but most don't) and 0% of can-standard (award notices — the tender window is already closed, there's nothing left to request). change-reason-description fills on 20% of cn-standard (a contract notice with a live corrigendum against it) and ~0-1% of can-standard/can-modif. Neither field is meaningful on an award notice; if you want them populated, filter noticeTypes: ["cn-standard"].

Why is placeOfPerformanceCity empty on most rows? TED's own place-of-performance-city-lot field is sparse — not a bug or a filter you're missing. Measured directly against TED's API (250-notice live sample, last 30 days, all countries, 2026-10-12): filled on 37.6% of notices overall, split by notice type — cn-standard (contract notices) 42% (64/152), can-standard (award notices) 36% (27/75), can-modif 12% (2/17), cn-social/can-social/pin-cfc-social/veat 0% on this sample's small counts (0/1-2 each). Compare placeOfPerformanceCountry, which fills on 93.6% (234/250) of the same sample — buyers reliably state a country but often skip a named city, especially on a nationwide or framework contract where no single city applies (one live row's "city" value was literally "Territorio nacional español" — TED's own free-text field, not a strict city name, for a contract performed anywhere in Spain). If you need city-level granularity, filter results to rows where placeOfPerformanceCity is non-empty rather than assuming every notice has one.

How is webhookUrl different from Apify's own platform webhooks? Apify's platform webhooks are configured separately per Task/Actor via the Console or the Webhooks API — useful if you already live in the Apify Console, but extra setup if you're calling this Actor's API directly and just want a completion ping. webhookUrl is a plain input field: set it on the run itself and it POSTs a JSON body (actorRunId, defaultDatasetId, finishedAt, pushed, pagesScanned, duplicateRowsDropped, totalNoticeCount, and — if watchLabel is set — watchSeeding/watchNewCount/baselineTruncated/baselineTruncatedTotal) once the run finishes and every row is already pushed and charged. It's best-effort — a slow or failing webhook only logs a warning, it never fails the run, changes the result set, or affects billing.

Notes

Only public data from an official EU government API is collected — no ToS or anti-bot risk. Issues or feature requests: support@fetchsmith.com. Also available as a hosted API at https://fetchsmith.com

Source code: https://github.com/Fetchsmith/fetchsmith/tree/main/actors/eu-ted-tenders-scraper

Engineering write-ups behind this Actor:

More tools: fetchsmith.com/tools