# Norway Bankruptcy Notices Scraper — Brreg Konkurs Gazette (`scrapersdelight/brreg-bankruptcy-notices-scraper`) Actor

Scrape Norway's official bankruptcy gazette (Brønnøysund konkurskunngjøringer): company, org number, notice type, court, case number, trustee name + e-mail, claim deadline, fristdag and first creditors' meeting. Filter by date, county, municipality and NACE industry. No login.

- **URL**: https://apify.com/scrapersdelight/brreg-bankruptcy-notices-scraper.md
- **Developed by:** [Scrapers Delight](https://apify.com/scrapersdelight) (community)
- **Categories:** Lead generation, Business, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 per notice returneds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## 🇳🇴 Norway Bankruptcy Notices Scraper — Brreg Konkurs Gazette

**Every Norwegian company bankruptcy, the day it is declared — with the court, the case number, the appointed trustee's name and e-mail address, the creditor claim deadline and the first creditors' meeting.**

This actor reads *Konkursregisteret*'s official gazette at `w2.brreg.no/kunngjoring`, the statutory publication the Brønnøysund Register Centre is required to make. Roughly **14,000–15,000 notices a year**, about **3,500 of them fresh bankruptcy openings**, covering the whole country.

***

### 🤔 What does this actor do?

It sweeps the gazette over any date range you choose, then opens each notice's official detail page and extracts the fields that only exist there.

- 🏢 **Company name + 9-digit organisation number** — joinable to any Norwegian company dataset
- ⚖️ **Court (tingrett) and case number** — e.g. `OSLO TINGRETT`, `26-114308KON-TOSL/08`
- 👤 **Trustee (bostyrer): name, e-mail address, postal address** — the one human who controls the estate
- ⏳ **Creditor claim deadline** (`frist for å melde krav`) + days remaining
- 📅 **Cut-off date** (`fristdagen`) — the date that decides which transactions can be clawed back
- 🏛️ **First creditors' meeting**: date, time and courtroom
- 🧾 **Notice type**: opening, compulsory dissolution, compulsory liquidation, proceedings stopped, estate closed
- 💡 **`Åpnet etter: Oppbud`** — the debtor filed for their *own* bankruptcy. Present on **89.4%** of openings (76 of 85, measured below), and one of the strongest credit signals in the dataset
- 🏗️ **Industry** — the debtor's own `Bransje/stilling` line, free-text NACE description — plus section / division / group **filters**
- 📍 **County, municipality, postal code and city**
- 💰 **Dividend percentage and distribution day** on closure notices
- 🔗 **Free join** to Brreg's open company register: NACE code, legal form, founding date, employee count, VAT status, website

***

### 🎯 Who buys this data

| Buyer | What they do with a row |
|---|---|
| **Debt collection / credit control** | A claim deadline is a hard countdown. Miss it and the debt is worthless. Every opening notice with a trustee e-mail is an actionable filing. |
| **Insolvency & restructuring law firms** | Competitive intelligence on which firms are being appointed as bostyrer, by which court, and how often. |
| **Credit bureaus & risk teams** | Same-day insolvency events keyed by organisation number, with the court record behind them. |
| **Asset buyers & liquidators** | Estates in a chosen industry and county, with the trustee's e-mail to contact about the assets. |
| **B2B sales & CRM hygiene** | Suppress bankrupt customers before you invoice them, and catch a customer's insolvency before the AR ages. |
| **Financial journalists & researchers** | A structured, queryable feed of the statutory record. |

***

### 🆚 Why not just use Brreg's free open data?

Brreg publishes an excellent free API — and it **cannot answer any of the questions above**. Verified 2026-09-04:

- `data.brreg.no/enhetsregisteret/api/docs` contains **zero** `kunngjøring` endpoints.
- The entity API exposes a single bare boolean: `"konkurs": true`.

That flag cannot tell you **when** the bankruptcy opened, **which court** opened it, the **case number**, **who** the trustee is, the trustee's **e-mail**, the **claim deadline**, the **fristdag**, or the **first creditors' meeting**. All of that lives on the gazette page and nowhere else. That gap is this actor.

This actor also uses the free API — for what it *is* good at. Turn on **Enrich from the open company register** and every row with an org number gains an `entity` block at no extra charge: legal form on **100%** of rows, and NACE code, founding date, VAT status and business address on the **44.9%** whose company record the register has not yet deleted (measured below).

***

### 📊 Measured field fill rates

**Per-notice-type fields are absent by design, not missing.** A closure notice
(*"Avslutning av bobehandling"*) legally carries only name, address, org number and case number —
there is no trustee or claim deadline to publish. The actor branches on notice type and emits
honest `null`s rather than inventing values.

Measured on **316 notices**, **30 August – 5 September 2026**, whole country, category 51, all
sub-types, every row detail-fetched (Apify run `MGGjNb8cGiVqd0hzA`). Notice-type mix in that
window: 168 × *Innstilling av bobehandling*, 85 × *Konkursåpning* (incl. 1 amendment), 48 ×
*Tvangsoppløsning*, 12 × *Avslutning av bobehandling*, 3 × *Tvangsavvikling*.

| Field | Fill | Note |
|---|---|---|
| `kid`, `detailUrl`, `companyName`, `orgNumber`, `registryId`, `subjectType`, `brregEntityUrl`, `noticeDate`, `noticeDateIso`, `noticeType`, `noticeTypeCode`, `noticeTypeName`, `county`, `countyNumber`, `regionName` | **100%** (316/316) | list page |
| `noticeTypeFull`, `publishedByRegister`, `publishedDate`, `publishedDateIso`, `isAmendment`, `isBankruptcyOpening`, `hasTrusteeContact`, `fields` | **100%** (316/316) | detail page, every notice type |
| `caseNumber` | **100%** (316/316) | |
| `court` | **99.4%** (314/316) | the 2 exceptions are notices from the same court that simply omit the *Tingrett* line; the court is still encoded in `caseNumber` (`26-140160KON-TIOF/TVAD`). A *Konkursåpning i hjemlandet* — a foreign parent's insolvency issued by Foretaksregisteret rather than a court — likewise has no Norwegian court or case number; none landed in this particular window |
| `postalCode`, `city`, `addressRaw` | **100%** (316/316) | **every published address yields a postcode and a city** |
| `addressStreet` | **98.4%** (311/316) | 5 debtors publish only a postcode and city, with no street line |
| `trusteeName`, `trusteeEmails`, `trusteeEmail`, `trusteeAddress`, `claimDeadline`, `claimDeadlineIso`, `daysUntilClaimDeadline`, `cutOffDate`, `cutOffDateIso`, `firstMeetingDate`, `firstMeetingTime`, `firstMeetingVenue`, `industry` | **43.0% overall (136/316) — 100% of the 85 bankruptcy openings** | only opening/liquidation notices carry a trustee, a deadline and an industry line; 53% of this window was *Innstilling av bobehandling* |
| `openedDate`, `openedDateIso` | 26.9% (85/316) — **100% of openings** | |
| `openedAfter` (`Oppbud`) | 24.1% (76/316) — **89.4% of openings** | debtor's own petition rather than a creditor's — a strong credit signal |
| `rulingPronouncedDate` | 53.2% (168/316) | |
| `rulingDate` | 16.1% (51/316) | |
| `dividendPercent`, `distributionDay` | closure notices only — 3.8% (12/316) | |
| `previousNames` | 2.2% (7/316) | |
| `amendmentHeadline` | 0.3% (1/316) | present only on amendment notices |
| `country`, `countryCode`, `homeCountryRegistrationNumber` | 0% in this window | foreign-parent (NUF) notices only; none occurred in these 7 days |
| `filterIndustrySectionName`, `filterIndustryDivisionName`, `filterIndustryGroupName` | 0% here — by definition | these echo **your industry filter**, not the row. See the note below |

**The free company-register join** (`enrichWithEntityRegistry`) measured separately on the same
window, 316 rows all with an org number (run `x3VQY4wlA6BrJ5nyQ`):

| `entity.*` sub-field | Fill |
|---|---|
| `organisasjonsform` (legal form) | **100%** (316/316) |
| `naceCode`, `naceDescription`, `registeredDate`, `foundedDate`, `vatRegistered`, `bankruptFlag`, `businessAddress` | **44.9%** (142/316) |
| `employees` | 9.5% (30/316) |
| `website` | 4.1% (13/316) |

The join returns an object for **every** row with an org number, but a company the register has
already **deleted** (`slettedato` — the normal end state after a closure notice) is served as a
name-and-legal-form stub, with NACE and the rest `null`. That is the open API's own behaviour, not
a fetch failure. Because this window was 53% closure notices, only 44.9% of rows still had a live
entity record.

#### ⚠️ `industry` vs `filterIndustry*` — which one is the row's own NACE

- **`industry`** is the debtor's own `Bransje/stilling` line from the notice. Detail-page only,
  43.0% overall / 100% of openings above. This is per-row data.
- **`entity.naceCode` / `entity.naceDescription`** is the structured NACE code from the company
  register, when you turn the free join on. Also per-row data.
- **`filterIndustrySectionName` / `filterIndustryDivisionName` / `filterIndustryGroupName`** are a
  **query echo**: they repeat the industry filter *you* sent so a landed dataset is
  self-describing. They are identical on every row of a run and `null` on every row of a run with
  no industry filter (measured: 0 of 547 filled unfiltered, 20 of 20 filled with the same constant
  under `industrySection: 70, industryDivision: 43`). They were named
  `industrySectionName` / `industryDivisionName` / `industryGroupName` before 2026-09-05; the
  `filter` prefix exists so they are never mistaken for the debtor's own industry.

#### 🧮 How many columns does a row actually have?

It depends on which optional blocks you switch on — all four counts measured on real runs:

| Configuration | Fields per row | Run |
|---|---|---|
| `fetchDetails: false` (list-only sweep) | **65** | `8yHANs2AzYahTKYO2` |
| **Default / prefill input** — detail on | **65** on list-only rows, **66** on detail-enriched rows | `G8S6P7NSuXO1X8dyo` |
| + `enrichWithEntityRegistry` | **67** | `FbzRYELvE6hsNb8Ww` |
| + `enrichWithEntityRegistry` **and** `includeFullNoticeText` **and** `includeRawNoticeHtml` | **69** | `9eyKYaKalfZVlcVYc` |

So **69 is the maximum-configuration count, not the default one.** The default row is 65–66 fields;
`entity`, `noticeText` and `rawNoticeHtml` are the three opt-ins that take it to 69.

*(Each count went up by 2 on 2026-09-07, build 0.1.8: every row now also carries
`searchWindowComplete` and `searchWindowMissingRanges` — see the coverage section under
Reliability. All four counts above were re-measured on that build, not adjusted on paper.)*

Set **Exclude notice sub-types** to `52, 54` if you only want notices that carry a trustee and a deadline, or tick **Only notices that name a trustee**.

***

### 🎯 The three filters that read the detail page

**Only notices that name a trustee**, **Claim deadline on/after**, **Claim deadline on/before** and
**Sort by claim deadline** cannot be answered from the gazette's list page — the trustee and the
deadline only exist on the notice itself. So when any of them is set, the actor **fetches the detail
page for every candidate in your window before filtering**, and **Maximum detail fetches is
deliberately ignored** for that run. The log says so when it happens.

That is not a detail worth hiding, because the alternative is silently wrong: capping the fetch
would mean the filter judges only the first *n* notices and throws the rest away unexamined, while
still reporting the answer as complete.

Measured today, 2026-09-05, on a 45-day country-wide window:

| Input | Register returned | Judged | Matched | Delivered | Time | Run |
|---|---|---|---|---|---|---|
| `onlyNoticesWithTrustee: true` | 1,156 notices (1,127 after personal notices are dropped) | 1,127 detail pages, 1,127 parsed (100%) | **542** | 50 (`maxItems` default) | 205 s | `rNYeFj5W19ZiEA6zj` |
| `claimDeadlineAfter: "2026-09-20"`, sorted by deadline | same 1,156 / 1,127 | 1,127 detail pages, 1,127 parsed (100%) | **281** | 50 (`maxItems` default) | 175 s | `85pqyvFQekDxmjkar` |

Two consequences worth planning around:

- **Your bill is capped by *Maximum notices to return*, not by *Maximum detail fetches*.** The cap is
  applied last, after filtering, so it never changes *which* notices match — only how many of the
  matches you receive. Raise it to collect the rest (542 and 281 above).
- **These runs take minutes, not seconds**, because they read every candidate notice, and their cost
  scales with the **window**, not with `maxItems`. The 45-day runs above took ~3 minutes and peaked
  at **226 MB** of the 512 MB default memory (1,127 notices held in memory). For a multi-month sweep
  *with one of these filters*, raise the run's memory or take the range in slices. A run that hits
  its own timeout mid-fetch says so, loudly, and tells you how many candidates it never examined —
  it will not pass off a short answer as a complete one.

Every other filter (county, municipality, industry, notice sub-type, company name, org numbers,
*only new*) is answered from the list page, so **Maximum detail fetches** applies normally there: the
default enriches the first 25 delivered rows and the rest arrive list-only with
`detailFetched: false` (measured: default input → 50 rows, 25 enriched, 12.1 s, run
`RIWBg9j6aLZuoyLVY`).

***

### ⚙️ Reliability — and the one setting that matters

The register is an old JSP that streams slowly, and its response grows with the date range:

| Range | Response | Rows | Time |
|---|---|---|---|
| 3 days | 236 KB | 187 | 2.3 s |
| 10 days | 507 KB | 441 | 3.7 s |
| 34 days | 978 KB | 882 | 4.8 s |
| **3 months** | — | — | **hard timeout at 60 s** |

So the actor **never issues one wide request**. It splits your range into slices of **`windowDays`** (default 14) and merges the results, deduplicated by the register's own notice id.

Measured over a full year of sweeps:

- **14-day slices: 25 of 26 requests succeeded (96.2%)**, 5,097 unique notices collected
- monthly slices: only 9 of 12 (75%) — three hard timeouts on 1–4 MB responses
- detail pages: **18 of 20 (90.0%)**
- **combined: 43 of 46 (93.5%)**

Both failure modes were transient connection resets that recover on retry, so `maxRequestRetries` defaults to 3. **Slicing is lossless**: a 31-day window returned 695 rows, and the identical range crawled as 5 contiguous weekly slices returned 695 unique notices — 0 missing, 0 extra.

#### 🔎 If a slice never returns, the run says so — and so does every row

96.2% is not 100%. Over a long sweep you should expect roughly one slice in twenty-six to fail even
after its retries, and a lost 14-day slice is **two weeks of Norway's bankruptcies missing**. So the
actor never lets a partial crawl pass itself off as a complete one. Every row carries two fields
beyond the window you asked for:

| Field | Meaning |
|---|---|
| `searchWindowFrom` / `searchWindowTo` | the window you **asked for** |
| `searchWindowComplete` | `true` only when **every** slice returned |
| `searchWindowMissingRanges` | the `dd.mm.yyyy–dd.mm.yyyy` ranges that were **never read**, so you can re-crawl exactly the gap |

and the run log leads with a matching `INCOMPLETE WINDOW` warning naming the same ranges.

Measured by inducing the failure (`requestTimeoutSecs: 10`, `maxRequestRetries: 0`,
`windowDays: 31` over 01.01–08.04.2026 — the three 31-day slices time out, the short tail slice
survives): the run stays `SUCCEEDED`, but the rows say `searchWindowComplete: false` with the three
lost ranges listed. On the **default** settings of a normal run all slices return and the field is
simply `true` (control run `rePiGBx9H6BLM7NRH`, 532 rows, `searchWindowComplete: true` on all 532).

The same check guards the empty answer. If slices are lost and the ones that did return happened to
be genuinely empty, the actor will **not** tell you the register published nothing — it says it
never read part of the window and names the ranges to re-run.

*(Fixed 2026-09-07, build 0.1.8. Before it, a failed slice left one mid-log warning while every
delivered row still stamped the full requested range — asserting coverage the crawl never had.)*

**Transport:** plain HTTP through the Apify **datacenter** proxy. Datacenter, Norwegian residential and US residential all returned byte-identical pages, so residential is not needed and is not the default. No browser, no cookies, no login.

***

### 👤 Personal bankruptcies are excluded by default

About **3% of gazette notices concern a natural person, not a company** — measured **15 of 547
notices** in a 14-day country-wide window (run `mAm4h1bQSKiKHc3eA`, 2026-09-05). The identifier the
register prints in the organisation-number column for those rows is the person's **6-digit date of
birth** in `DDMMYY`, not an org number. Norwegian D-numbers add 40 to the day, so `530778` reads as
13.07.1978.

This actor detects those rows, **never writes that value into `orgNumber`** (it stays `null`, and
`brregEntityUrl` stays `null` too), tags them `subjectType: "person"`, and **excludes them by
default**. They are not business leads.

**If you switch *Include personal bankruptcies* on, be clear about what you are opting into.** The
register's own key is still emitted verbatim, so on those rows:

- **`registryId` contains the individual's date of birth** — e.g. `"companyName": "LOUKATOS
  ALEXANDROS"` with `"registryId": "051180"`. Every person row in the measured window carried one
  (15 of 15).
- **`detailUrl` contains it too**, as the `sokeverdi=` query parameter, because that is how the
  register addresses the notice.
- `companyName` holds the individual's **full name**.

A name plus a date of birth is personal data under GDPR, and you become the controller for it. If
you want the notices without that, leave the toggle off — which is the default.

***

### 💵 Pricing

| Event | Price | What it covers |
|---|---|---|
| **Per notice returned** | **$0.002** | Each notice delivered: company, org number, notice type and date, county, official link |
| **Per notice detail** | **$0.004** | Court, case number, trustee name + e-mail + address, claim deadline, fristdag, creditors' meeting, industry |

You are charged **only for rows you actually receive**. Filtered-out notices and anything beyond your **Maximum notices** cap are never billed, and detail is charged only for delivered rows — reading a notice's detail page to decide whether it matches your filter is never billed. On an ordinary sweep **Maximum detail fetches** caps the enrichment charge separately; when a detail-reading filter is on it does not apply (see above) and **Maximum notices to return** is the cap that bounds the bill.

The comparable lane — European insolvency-gazette scrapers — prices list rows at a median of **$0.004** and full-notice tiers from **$0.004 to $0.030**. Both events here sit at or below the cheap end.

A typical month of nationwide notices with full enrichment (~1,200 notices) costs about **$7.20**.

***

### 🚀 Quick start

**Everything that went bankrupt in Norway last week, with trustee contact details:**

```json
{ "lastNDays": 7, "onlyNoticesWithTrustee": true, "maxItems": 0 }
```

*(The trustee filter reads every candidate's detail page automatically — **Maximum detail fetches**
does not apply to it. `maxItems: 0` lifts the 50-row default cap.)*

**Construction-company bankruptcies in Vestland last month:**

```json
{
  "datoFra": "01.08.2026", "datoTil": "31.08.2026",
  "region": "300", "county": "46",
  "industrySection": "70",
  "noticeTypes": ["56"]
}
```

**A daily monitor that only ever reports what is new:**

```json
{ "lastNDays": 3, "onlyNew": true, "seenStoreName": "my-konkurs-watch", "maxItems": 0 }
```

**Watch a customer portfolio for insolvency:**

```json
{ "lastNDays": 30, "orgNumbers": ["916363281", "924566876"], "maxItems": 0 }
```

**Estates you can still file a claim against:**

```json
{ "lastNDays": 45, "claimDeadlineAfter": "2026-09-20", "sortBy": "claimDeadline", "sortOrder": "asc" }
```

*Measured exactly as printed, 2026-09-05 (run `85pqyvFQekDxmjkar`): 1,156 notices crawled, all 1,127
company candidates detail-read, **281 estates still open to claims**, the soonest-deadline 50
delivered under the default `maxItems`. Raise `maxItems` to take all 281; the run takes about three
minutes because it reads every candidate notice.*

***

### ❓ FAQ

**Do I need an account or login?**
No. The gazette is a public statutory publication. No login, no cookies, no API key.

**How far back does the archive go?**
Years. A 2021 case number surfaced in an August 2026 amendment notice. Use `datoFra`/`datoTil` and keep `windowDays` at 14 for a long sweep.

**Can I get the notices in English?**
Yes. Set **Notice language** to `en` and the register returns its own official English translation, with English field labels. The parser reads both languages, and the company names, dates, org numbers and case numbers are identical either way — verified field by field on the same notices in both languages.

Classification is language-independent: `noticeTypeCode`, `isBankruptcyOpening` and the
**Exclude notice sub-types** filter behave identically in `nb` and `en`. Verified on the same
547-notice window parsed in both languages — identical code mix (52 × 28, 54 × 262, 56 × 163,
60 × 10, 73 × 84) — and live on run `8rj6eu8unwzTBp5qq` (`en`, `excludeNoticeTypes: [52, 54]`),
which dropped 140 rows and delivered 20 carrying real codes. One deliberate exception:
`noticeTypeName` is the register's **canonical Norwegian sub-type name** in both languages, because
it is the stable machine label for `noticeTypeCode`. The English display label is in `noticeType`,
and the notice's own English headline is in `noticeTypeFull`.

> **Fixed 2026-09-07 (build 0.1.8).** On builds up to 0.1.7 `language: "en"` silently nulled
> `noticeTypeCode` and `noticeTypeName`, forced `isBankruptcyOpening` to `false`, and turned
> `excludeNoticeTypes` into a no-op that still billed you for the notices you excluded (run
> `UxM06nd2BluAG3ps7`: 12 of 20 charged rows were the excluded types 52/54). If you ran this actor
> in English before that date, re-run — the type fields in that output are wrong.

**What is the difference between the notice types?**
`Konkursåpning` (56) = bankruptcy opened, the richest row. `Tvangsoppløsning` (73) and `Tvangsavvikling` (60) = the court forced the company into dissolution or liquidation, also with a trustee. `Innstilling av bobehandling` (54) = proceedings stopped because the estate cannot fund them. `Avslutning av bobehandling` (52) = estate closed, sometimes with a dividend percentage.

**What is `openedAfter: "Oppbud"`?**
The company petitioned for its *own* bankruptcy rather than being pushed into it by a creditor. It appeared on **89.4% of opening notices** (76 of 85) in the measured week above, and is a meaningfully different credit signal from a creditor-forced bankruptcy.

**How many columns will I get?**
65 on a list-only sweep, 65–66 on the default input, 67 with the free company-register join, and 69 with all three optional blocks (`entity`, `noticeText`, `rawNoticeHtml`) switched on. Measured run by run in the table above — 69 is the maximum, not the default.

**Does the dataset ever contain personal data?**
Two things. The **trustee's** name, e-mail and postal address — a professional the register publishes precisely so creditors can reach them. And, only if you opt in to **personal bankruptcies**, the individual's full name in `companyName` plus their **date of birth in `registryId`** (and in `detailUrl`). Personal bankruptcies are off by default. See the personal-data section below.

**What is the `fristdag` / cut-off date?**
The reference date used to decide which of the debtor's transactions can be reversed. It is often months before the bankruptcy opened, and it matters a great deal to anyone who traded with the company recently.

**How do I deduplicate against my own database?**
Use `kid`, the register's own notice id. It is unique per notice and stable. **Do not use `orgNumber`** — one company legitimately receives several notices (opening, stopped, closed) across the life of its case.

**Why do some rows have no trustee or claim deadline?**
Because the register does not publish one for that notice type. See the fill-rate table above.

**Can I run this on a schedule?**
Yes — that is what `lastNDays` + `onlyNew` are for. `onlyNew` keeps its memory in a **named** key-value store, so it genuinely persists between runs instead of reporting everything as new each time.

**Will a run ever fail on me?**
Only when something is actually wrong. A genuinely empty result (a rare sub-type, a narrow filter) exits cleanly with an empty dataset. The actor fails loudly only when the register reports hits that the parser could not read, when every request failed, or when your filter codes are invalid — and in that last case it tells you exactly which values are valid.

***

### 📤 Output sample

```json
{
  "kid": "20260000691757",
  "companyName": "ROSENHOLM ANLEGG AS",
  "orgNumber": "916363281",
  "brregEntityUrl": "https://virksomhet.brreg.no/oppslag/enheter/916363281",
  "noticeDate": "14.08.2026",
  "noticeDateIso": "2026-08-14",
  "noticeType": "Konkursåpning",
  "noticeTypeCode": 56,
  "noticeTypeFull": "Konkurs - åpning",
  "isBankruptcyOpening": true,
  "county": "Oslo",
  "regionName": "Østlandet",
  "addressStreet": "Rosenholmveien 17",
  "postalCode": "1252",
  "city": "OSLO",
  "court": "OSLO TINGRETT",
  "caseNumber": "26-112296KON-TOSL/08",
  "openedDate": "14.08.2026",
  "claimDeadline": "18.09.2026",
  "claimDeadlineIso": "2026-09-18",
  "daysUntilClaimDeadline": 14,
  "cutOffDate": "03.07.2026",
  "firstMeetingDate": "05.10.2026",
  "firstMeetingTime": "09:20",
  "firstMeetingVenue": "Oslo tingrett, sal 617",
  "industry": "Annen spesialisert bygge- og anleggsvirksomhet ikke nevnt annet sted",
  "previousNames": "MILJØ MUR OG BETONG AS",
  "trusteeName": "Adv. Audun Mørk Kleppestø",
  "trusteeEmail": "aukl@bull.no",
  "trusteeAddress": "Postboks 6604 St.Olavs Plass, 0129 OSLO",
  "hasTrusteeContact": true,
  "publishedByRegister": "Konkursregisteret",
  "publishedDate": "14.08.2026",
  "entity": {
    "naceCode": "43.990",
    "organisasjonsform": "Aksjeselskap",
    "registeredDate": "2015-12-09",
    "foundedDate": "2015-12-04",
    "vatRegistered": false,
    "bankruptFlag": true
  },
  "detailUrl": "https://w2.brreg.no/kunngjoring/hent_en.jsp?kid=20260000691757&sokeverdi=916363281&spraak=nb"
}
```

***

### ⚖️ Legal, robots and personal data

**`robots.txt`:** `w2.brreg.no` **serves no robots.txt at all** — the path returns `404` (verified 2026-09-04).

**Robots meta tag:** the results page carries, verbatim:

```html
<meta name='ROBOTS' content='NOINDEX, NOFOLLOW'>
```

That directive governs **search-engine indexing** of the results page. This actor does not build a search index; it reads a statutory publication that the Brønnøysund Register Centre is legally required to publish, at ordinary human speed, without a login and without circumventing any access control.

**Personal data.** Two things in this dataset are personal data under GDPR:

1. **Trustee contact details.** `trusteeName`, `trusteeEmails` and `trusteeAddress` identify a named individual — an advokat acting in a professional capacity, published by the register precisely so creditors can contact them. Downstream use is the buyer's responsibility as data controller: contacting a trustee about the estate is what the register published them for; adding them to an unrelated marketing list is not.
2. **Personal bankruptcies.** Excluded by default (see above). Enabling them is a deliberate choice with a deliberate consequence, and the consequence is field-level: `companyName` carries the individual's **full name**, and **`registryId` carries their 6-digit date of birth** (`DDMMYY`), which also appears inside `detailUrl` as `sokeverdi=`. `orgNumber` and `brregEntityUrl` stay `null` — the birth date is never laundered into a company field — but it is present in the row, and you are the controller for it. Measured: 15 of 547 notices in a 14-day country-wide window.

Nothing here bypasses authentication, a CAPTCHA, or a rate limit. No login is used or required. You are responsible for how you use the data, including under GDPR and the Norwegian Personal Data Act.

***

*Data source: Konkursregisteret / Brønnøysundregistrene. This actor is not affiliated with or endorsed by the Brønnøysund Register Centre.*

# Actor input Schema

## `lastNDays` (type: `integer`):

Scrape the last N days of notices, ending today. Best choice for a scheduled monitor. Overrides the fixed date range below when set. Leave empty and set the two dates instead for a historical sweep. With neither set, the actor uses the last 7 days.

## `datoFra` (type: `string`):

Start of a fixed date range, e.g. 01.08.2026. Used only when 'Last N days' is empty. The archive reaches back years.

## `datoTil` (type: `string`):

End of a fixed date range, e.g. 31.08.2026. Used only when 'Last N days' is empty.

## `windowDays` (type: `integer`):

The register streams slowly and its response grows with the range: a 3-month request hard-fails at 60s. The crawler therefore splits your range into slices of this many days. Measured: 14-day slices scored 25/26 (96.2%) across a full year, monthly slices only 9/12 (75%). Leave at 14 unless you have a reason. Slicing is lossless — a 31-day window and the same range as 5 weekly slices both returned exactly 695 unique notices.

## `noticeCategory` (type: `string`):

Which family of Brreg gazette notices to read. Default 51 = Konkurs/tvangsavvikling (bankruptcy, compulsory dissolution and liquidation) — the insolvency lane this actor is built and priced for. Industry filters are only honoured for category 51; the register ignores them for every other category.

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

Restrict to specific sub-types within the chosen category. Leave empty for all of them (one request instead of one per type — faster). Codes shown are for category 51. The actor issues one request per selected sub-type and merges the results, deduplicated by notice id.

## `excludeNoticeTypes` (type: `array`):

Drop these sub-types after parsing. Handy to keep openings and discard closures: exclude 52 and 54 to remove 'bobehandling avsluttet' and 'innstilt', which carry no trustee or claim deadline. A notice whose label is not recognised is never dropped.

## `region` (type: `string`):

Region of the debtor's registered address. 0 = the whole country (default).

## `county` (type: `string`):

County number. Must sit inside the selected region — the actor validates the pair and names the valid counties if it does not. Leave empty for all counties.

## `municipality` (type: `string`):

Four-digit municipality number, e.g. 301 for Oslo, 1103 for Stavanger, 4601 for Bergen. Requires a county to be set; the actor checks the municipality really belongs to it. Leave empty for all.

## `industrySection` (type: `string`):

Filter by the debtor's industry. This is the single highest-value filter for niche lead generation — 'construction companies that went bankrupt in Vestland last month' is one run. Only honoured for notice category 51. The chosen section's name is echoed back on every row as filterIndustrySectionName; the debtor's OWN industry is the separate `industry` field (and entity.naceCode when the company-register join is on).

## `industryDivision` (type: `string`):

Narrow within the section, e.g. 41 = construction of buildings, 43 = specialised construction, 56 = food & beverage service. Requires the matching industry section; the actor rejects a mismatched pair rather than silently returning unfiltered rows. Echoed back on every row as filterIndustryDivisionName.

## `industryGroup` (type: `string`):

Narrowest industry filter, e.g. 210 under division 43 = electrical installation. Requires the division, because group codes are only unique WITHIN a division (NACE 01.11 and 03.11 both submit 110). An unknown code is rejected with the list of valid groups for your division. Echoed back on every row as filterIndustryGroupName.

## `language` (type: `string`):

The register publishes each notice in Norwegian and in its own official English translation. 'en' returns English notice text and English field labels; the parser reads both. Company names, dates and case numbers are identical either way.

## `companyNameContains` (type: `string`):

Keep only notices whose company name contains this text (case-insensitive).

## `orgNumbers` (type: `array`):

Watch a specific portfolio: keep only notices for these 9-digit Norwegian org numbers. Applied over the date window you scrape, so widen the window when checking a portfolio.

## `includePersonalBankruptcies` (type: `boolean`):

Off by default. About 3% of gazette notices concern a NATURAL PERSON rather than a company (measured 2026-09-05: 15 of 547 notices in a 14-day country-wide window). On those rows the register prints a 6-digit DDMMYY DATE OF BIRTH where a company would have its organisation number. The actor never writes that value into orgNumber, but it IS emitted verbatim in registryId, and it also appears inside detailUrl as the sokeverdi parameter — next to the individual's full name in companyName. That is personal data under GDPR. These rows are not business leads, so they are excluded unless you explicitly opt in; if you do, you take on the controller responsibility for it.

## `onlyNoticesWithTrustee` (type: `boolean`):

The debt-collection and insolvency-services filter: drop closure notices that carry no bostyrer, so every row has a named contact to approach. Requires detail fetching, and every candidate in your window is detail-checked before the filter runs — 'Maximum detail fetches' is ignored so the filter can never answer from a truncated sample. Cap the bill with 'Maximum notices to return'.

## `claimDeadlineAfter` (type: `string`):

Keep only notices whose creditor claim deadline falls on or after this date (YYYY-MM-DD or dd.mm.yyyy). Use it to surface estates you can still file a claim against. Requires detail fetching; rows without a deadline are excluded while this filter is set. Every candidate in your window is detail-checked before the filter runs — 'Maximum detail fetches' is ignored so the filter cannot answer from a truncated sample; cap the bill with 'Maximum notices to return'.

## `claimDeadlineBefore` (type: `string`):

Keep only notices whose creditor claim deadline falls on or before this date (YYYY-MM-DD or dd.mm.yyyy). Same as the bound above: it requires detail fetching, every candidate in your window is checked, and rows with no deadline are excluded while it is set.

## `onlyNew` (type: `boolean`):

For scheduled monitors: emit only notices whose id is not already in the named key-value store below, then record what was delivered. The store is NAMED and therefore survives between runs.

## `seenStoreName` (type: `string`):

Named key-value store backing 'Only new'. Use a distinct name per saved search so two monitors do not share a memory.

## `fetchDetails` (type: `boolean`):

On by default, and the reason this actor exists: the detail page is the ONLY place that carries the court, case number, trustee name and e-mail, claim deadline, cut-off date (fristdag) and first creditors' meeting. Brreg's free open-data API exposes none of them — it has only a bare konkurs true/false flag. Turn off for a cheap list-only sweep.

## `includeTrusteeContact` (type: `boolean`):

Emit trusteeName, trusteeEmails, trusteeEmail and trusteeAddress. These are a named individual's professional contact details — see the README's GDPR note.

## `includeFullNoticeText` (type: `boolean`):

Add noticeText, the complete published wording of the notice as plain text.

## `includeRawNoticeHtml` (type: `boolean`):

Add rawNoticeHtml, the register's own notice fragment, for buyers who want to re-parse or archive it verbatim. Makes rows much larger.

## `enrichWithEntityRegistry` (type: `boolean`):

Join each company to Brreg's open Enhetsregisteret API for NACE code and description, legal form, registration and founding dates, employee count, VAT registration, website and business address. Free, no key, no extra charge — one extra request per company. Companies the register has already DELETED (common on closure notices) return name and legal form only: measured 2026-09-05, 142 of 316 rows came back with a NACE code, all 316 with a legal form (run x3VQY4wlA6BrJ5nyQ).

## `maxItems` (type: `integer`):

Hard cap on delivered rows, and therefore on your bill — applied last, after every filter, so it never changes which notices match. Defaults to 50 so a run started with no input stays cheap; raise it for real sweeps. 0 means no cap.

## `maxDetailFetches` (type: `integer`):

Caps the paid enrichment event on a plain sweep: the first 25 delivered rows are enriched and the rest arrive list-only with detailFetched: false. Set 0 to enrich every delivered row. IT DOES NOT APPLY when a detail-dependent filter is on — 'Only notices that name a trustee', either claim-deadline bound, or sorting by claim deadline. Those are judged ON the detail page, so detail is fetched for every candidate in your window first (the run log says so when it happens) and the bill stays capped by 'Maximum notices to return' instead. Capping the fetch there would silently discard never-examined candidates as non-matching.

## `sortBy` (type: `string`):

Field to order the dataset by. 'claimDeadline' requires detail fetching and is only meaningful across every candidate, so choosing it detail-fetches the whole window before sorting and ignores 'Maximum detail fetches'. The cap on delivered rows still applies afterwards.

## `sortOrder` (type: `string`):

Direction for the sort field. Notices with no value for the chosen field are always placed last, whichever direction you pick.

## `detailConcurrency` (type: `integer`):

Parallel detail requests. Measured on the live register: 4/4 in 2.4s and 8/8 in 2.8s with no throttling. 8 is the tested default.

## `requestTimeoutSecs` (type: `integer`):

Per-request timeout. The register is slow on wide ranges; keep the slice size small rather than raising this.

## `maxRequestRetries` (type: `integer`):

The register's observed failure mode is a transient ECONNRESET / connection error that succeeds on retry, so retries matter more than proxy class. Each retry takes a fresh proxy IP.

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

Apify datacenter proxy is the default and is enough: datacenter, Norwegian residential and US residential all returned byte-identical pages when measured. Residential costs more for no gain. The country pin is exposed for buyers bringing their own proxies.

## Actor input object example

```json
{
  "lastNDays": 7,
  "datoFra": "01.08.2026",
  "datoTil": "31.08.2026",
  "windowDays": 14,
  "noticeCategory": "51",
  "noticeTypes": [],
  "excludeNoticeTypes": [],
  "region": "0",
  "county": "",
  "municipality": "",
  "industrySection": "0",
  "industryDivision": "",
  "industryGroup": "",
  "language": "nb",
  "companyNameContains": "",
  "orgNumbers": [],
  "includePersonalBankruptcies": false,
  "onlyNoticesWithTrustee": false,
  "claimDeadlineAfter": "",
  "claimDeadlineBefore": "",
  "onlyNew": false,
  "seenStoreName": "brreg-bankruptcy-notices-seen",
  "fetchDetails": true,
  "includeTrusteeContact": true,
  "includeFullNoticeText": false,
  "includeRawNoticeHtml": false,
  "enrichWithEntityRegistry": false,
  "maxItems": 50,
  "maxDetailFetches": 25,
  "sortBy": "noticeDate",
  "sortOrder": "desc",
  "detailConcurrency": 8,
  "requestTimeoutSecs": 60,
  "maxRequestRetries": 3,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `notices` (type: `string`):

Company, org number, notice type and date, county, court, case number, trustee name + e-mail, creditor claim deadline, cut-off date (fristdag), first creditors' meeting, industry and address.

# 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 = {
    "lastNDays": 7,
    "windowDays": 14,
    "noticeCategory": "51",
    "region": "0",
    "industrySection": "0",
    "fetchDetails": true,
    "maxItems": 50,
    "maxDetailFetches": 25,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapersdelight/brreg-bankruptcy-notices-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 = {
    "lastNDays": 7,
    "windowDays": 14,
    "noticeCategory": "51",
    "region": "0",
    "industrySection": "0",
    "fetchDetails": True,
    "maxItems": 50,
    "maxDetailFetches": 25,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("scrapersdelight/brreg-bankruptcy-notices-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 '{
  "lastNDays": 7,
  "windowDays": 14,
  "noticeCategory": "51",
  "region": "0",
  "industrySection": "0",
  "fetchDetails": true,
  "maxItems": 50,
  "maxDetailFetches": 25,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call scrapersdelight/brreg-bankruptcy-notices-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,scrapersdelight/brreg-bankruptcy-notices-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/B1m0jTZZgNJkpxqcO/builds/9gpdhtutKLKX7fcFZ/openapi.json
