# Norway Public Tenders Scraper: Doffin Notices (`datadesk-io/norway-tenders-scraper`) Actor

Scrape Norwegian public tenders from Doffin, the national notification database: title, description, buyer and org number, place, notice type, status, publication date, deadline and link. Filter by keyword, CPV, region. Alerts. $1.50 per 1,000.

- **URL**: https://apify.com/datadesk-io/norway-tenders-scraper.md
- **Developed by:** [DataDesk](https://apify.com/datadesk-io) (community)
- **Categories:** Lead generation, Business
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.20 / 1,000 tenders

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Norway Public Tenders Scraper

Monitor **Norwegian public procurement** from **Doffin** (doffin.no), the **national database for public notices**: **160,000+ notices** from municipalities, ministries, hospitals and state companies. Each record has **title, description, buyer name and org number, place of performance, notice type, status, publication date, deadline, estimated value when given, green/social procurement labels and the notice link**. Filter by **keyword, CPV code, region, status and date**. No login, no key. **$1.50 per 1,000 tenders.**

### What you get

| Field group | Fields |
|---|---|
| Tender | tenderId, title, description, noticeType, status, labels |
| Buyer | buyerName, buyerOrgNumber, buyers |
| Place | placeOfPerformance, locationCodes |
| Dates and value | publishedAt, issuedAt, deadlineAt, estimatedValue, estimatedValueCurrency, sentToTed |
| Link | url |

### Sources and coverage

| Source | Coverage | Data |
|---|---|---|
| **Doffin** (`doffin.no`) | Norway national public notices, EEA and national thresholds | Competitions, results, planning and advisory notices |

### How to use it

1. Click **Try for free** (or **Start**): the prefilled input runs a quick test.
2. Adjust the filters (see examples below).
3. Click **Start** and wait a few seconds.
4. Open the **Output** tab and export as **JSON, CSV, Excel, XML or HTML**, or read the dataset via API.

### Input examples

**Open IT tenders:**

```json
{"keywords": ["programvare"], "status": ["ACTIVE"], "daysBack": 60, "maxTenders": 100}
```

**Software CPV notices in Oslo:**

```json
{"cpvCodes": ["72000000"], "locationCodes": ["NO081"], "daysBack": 90, "maxTenders": 300}
```

**Daily alert for construction tenders:**

```json
{"keywords": ["bygg"], "noticeTypes": ["ANNOUNCEMENT_OF_COMPETITION"], "daysBack": 2, "onlyNewTenders": true, "alertsKey": "construction-no"}
```

#### Input fields

| Field | Type | Description |
|---|---|---|
| `keywords` | array | Words in Norwegian or English, e.g. programvare, bygg, software. Leave empty for all notices. |
| `daysBack` | integer | Only notices published in the last N days. 0 = all dates (max 1,000 notices per query). |
| `status` | array | ACTIVE, AWARDED, EXPIRED or CANCELLED. |
| `noticeTypes` | array | e.g. ANNOUNCEMENT_OF_COMPETITION (open tender), RESULT, ANNOUNCEMENT_OF_CONCLUSION_OF_CONTRACT, PLANNING, ADVISORY_NOTICE. |
| `cpvCodes` | array | CPV codes, e.g. 72000000 (IT services), 48000000 (software), 45000000 (construction). |
| `locationCodes` | array | NUTS codes, e.g. NO081 (Oslo), NO0A1 (Vestland), NO060 (Trøndelag). |
| `maxTenders` | integer | Stop after this many notices. |
| `onlyNewTenders` | boolean | Return only tenders not seen in previous runs with the same alerts key. Schedule daily for alerts. |
| `alertsKey` | string | Name for this alert memory (use a different key per saved search). |

### Output example

*Example values from a local test run.*

```json
{
  "source": "doffin",
  "tenderId": "2026-117303",
  "title": "Markedsdialog: Helhetlige IT-driftstjenester for Fjellinjen",
  "description": "Fjellinjen inviterer leverandører til skriftlig markedsdialog i forbindelse med en kommende anskaffelse av helhetlige IT-driftstjenester for virksomhetens digitale arbeidsflate og underliggende IT-miljø. Formålet med markedsdialogen er å få innsikt i markedets vurderinger av den planlagte leveransen og utkast til kravspesifikasjon. Fjellinjen ønsker særlig innspill til om kravene er tydelige, relevante og forholdsmessige, og om de legger til rette for god konkurranse, sikker og stabil leveranse, teknologisk fleksibilitet og hensiktsmessig videreutvikling i avtaleperioden. Leverandørene inviteres til å gi skriftlige tilbakemeldinger på spørsmålene i dialogskjemaet. Fjellinjen er også interessert i øvrige innspill som kan bidra til å forbedre konkurransegrunnlaget, tydeliggjøre ansvarsdeling og sikre en balansert og fremtidsrettet leveransemodell. Innspillene vil bli brukt som del av forberedelsen av anskaffelsen. Deltakelse i markedsdialogen er frivillig og er ikke en forutsetning for å kunne delta i en senere konkurranse. Se vedlegg for beskrivelse av leveransen og Fjellinjen.",
  "noticeType": "ADVISORY_NOTICE",
  "status": null,
  "buyerName": "Fjellinjen",
  "buyerOrgNumber": "941856543",
  "buyers": "Fjellinjen",
  "placeOfPerformance": "Oslo",
  "locationCodes": "NO081",
  "estimatedValue": null,
  "estimatedValueCurrency": null,
  "publishedAt": "2026-11-07",
  "issuedAt": "2026-11-06T09:35:44Z",
  "deadlineAt": null,
  "sentToTed": false,
  "labels": null,
  "url": "https://www.doffin.no/notices/2026-117303"
}
```

#### Output fields

| Field | Description |
|---|---|
| `tenderId` | Doffin notice ID (e.g. 2026-117319) |
| `title` | Notice heading |
| `description` | Short description |
| `noticeType` | COMPETITION, RESULT, PLANNING... |
| `status` | ACTIVE, AWARDED, EXPIRED, CANCELLED |
| `buyerName / buyerOrgNumber` | Contracting authority |
| `placeOfPerformance` | Region |
| `deadlineAt` | Tender deadline |
| `estimatedValue` | Only when published |
| `url` | Doffin notice page |

### Pricing

Pay-per-event: **$0.005** once per run that saves results + **$0.002 per tender** ($1.5 / 1,000). Runs that save nothing are not charged.

| Tenders saved | Approx. cost |
|---|---|
| 20 | $0.035 |
| 100 | $0.155 |
| 1,000 | $1.505 |
| 10,000 | $15.005 |

### Use cases

- Bid teams monitoring Norwegian tenders by CPV or keyword
- Lead lists of public buyers (with org numbers) for B2B sales
- Market analysis of public spend by region
- Daily alerts for new competitions

### Integrations / API

Works with the Apify API, Schedules, webhooks, Make, Zapier, n8n and MCP. Example:

```bash
curl "https://api.apify.com/v2/acts/datadesk-io~norway-tenders-scraper/run-sync-get-dataset-items" \
  -H "Authorization: Bearer $APIFY_TOKEN" -H "Content-Type: application/json" \
  -d '{"keywords": ["programvare"], "status": ["ACTIVE"], "daysBack": 60, "maxTenders": 100}'
```

Python:

```python
from apify_client import ApifyClient
client = ApifyClient("<APIFY_TOKEN>")
run = client.actor("datadesk-io/norway-tenders-scraper").call(run_input={"keywords": ["programvare"], "status": ["ACTIVE"], "daysBack": 60, "maxTenders": 100})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

### MCP

Use this Actor from an MCP client (Cursor, Claude Desktop, etc.) through the Apify MCP server (`datadesk-io/norway-tenders-scraper`).

### Alerts mode

Turn on the **Only new** option and schedule the Actor daily: each run returns only tenders not seen in earlier runs with the same alerts key (nothing is charged when there is nothing new).

### FAQ

**Do I need a key?** No. The Actor reads the same public search as doffin.no.

**Can I get every notice ever published?** Doffin exposes at most 1,000 hits per query, so the Actor splits long periods into weekly windows automatically.

**Are documents included?** No: you get structured data and the notice link; documents are on Doffin.

### Limitations

- Doffin exposes the top 1,000 hits per query; the Actor splits by week when daysBack is set.
- Estimated value is empty for most notices.
- Descriptions are short summaries, not the full tender documents.

### Support

Questions, bugs or a missing field? Email **datadesk.io@proton.me** or open an issue on the Actor page.

***

**ES:** Extrae licitaciones públicas noruegas de **Doffin**: comprador, nº org., CPV, estado, plazo y enlace. Filtros por palabra, CPV y región. **$1,50 / 1.000.**
**PT:** Extrai licitações públicas norueguesas do **Doffin**: comprador, nº org., CPV, status, prazo e link. **$1,50 / 1.000.**

# Actor input Schema

## `keywords` (type: `array`):

Words in Norwegian or English, e.g. programvare, bygg, software. Leave empty for all notices.

## `daysBack` (type: `integer`):

Only notices published in the last N days. 0 = all dates (max 1,000 notices per query).

## `status` (type: `array`):

ACTIVE, AWARDED, EXPIRED or CANCELLED.

## `noticeTypes` (type: `array`):

e.g. ANNOUNCEMENT_OF_COMPETITION (open tender), RESULT, ANNOUNCEMENT_OF_CONCLUSION_OF_CONTRACT, PLANNING, ADVISORY_NOTICE.

## `cpvCodes` (type: `array`):

CPV codes, e.g. 72000000 (IT services), 48000000 (software), 45000000 (construction).

## `locationCodes` (type: `array`):

NUTS codes, e.g. NO081 (Oslo), NO0A1 (Vestland), NO060 (Trøndelag).

## `maxTenders` (type: `integer`):

Stop after this many notices.

## `onlyNewTenders` (type: `boolean`):

Return only tenders not seen in previous runs with the same alerts key. Schedule daily for alerts.

## `alertsKey` (type: `string`):

Name for this alert memory (use a different key per saved search).

## Actor input object example

```json
{
  "keywords": [
    "programvare"
  ],
  "daysBack": 30,
  "maxTenders": 20,
  "onlyNewTenders": false
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "keywords": [
        "programvare"
    ],
    "daysBack": 30,
    "maxTenders": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("datadesk-io/norway-tenders-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "keywords": ["programvare"],
    "daysBack": 30,
    "maxTenders": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("datadesk-io/norway-tenders-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "keywords": [
    "programvare"
  ],
  "daysBack": 30,
  "maxTenders": 20
}' |
apify call datadesk-io/norway-tenders-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,datadesk-io/norway-tenders-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/0TA471riJd4DztuIf/builds/BCkbDcgIcz8tfGbwv/openapi.json
