Brønnøysund Company Lookup: Norway Business Registry API
Pricing
from $2.00 / 1,000 successful lookups
Brønnøysund Company Lookup: Norway Business Registry API
Look up Norwegian companies by organization number against Brønnøysund Register Centre's official, free registry. Get legal form, NACE industry code, address, employee count, VAT status, and bankruptcy flags. Pay only for numbers that resolve.
Pricing
from $2.00 / 1,000 successful lookups
Rating
0.0
(0)
Developer
Adrian Voss
Maintained by CommunityActor stats
1
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
Brønnøysund Company Lookup
You give this actor a list of Norwegian organization numbers. It looks each one up against the Brønnøysund Register Centre's official, free Enhetsregisteret (Central Coordinating Register for Legal Entities) API and returns one flat row per number — legal name, legal form, NACE industry code, registered address, employee count, VAT registration, and bankruptcy/liquidation status. No API key, no scraping: this calls the Norwegian government's own registry endpoint directly, for every input, every run.
Who it's for
The accountable_eel catalogue sells company intelligence columns for outbound. Each actor takes a list of domains or company identifiers and returns one flat, stably-named row per input — firmographics, registry IDs, tech stack, email route, hiring activity — the shape a Clay table, an n8n workflow, or an AI agent can consume without post-processing. Pricing is pay-per-event and per-domain: a few tenths of a cent for a row that was actually found, and nothing for a miss, so a list that doesn't enrich costs you next to nothing. Where an official source exists — VIES, GLEIF, SEC EDGAR, Brønnøysund, PRH, RDAP — it is queried directly instead of scraped. No seat licence, no monthly minimum, no credit system to decode. For Norway specifically, that official source is Brønnøysund's Enhetsregisteret — the same register a Norwegian bank or notary would check.
Why this one
- Official registry, not a scrape.
src/target.jshitsdata.brreg.no/enhetsregisteret/api/enheter/<orgnr>directly — the same JSON the Brønnøysund website itself is built on. - Compliance flags in the same row as firmographics. Bankruptcy and under-liquidation status come back alongside legal form, industry code, and employee count — you don't make a second call to ask "is this company still solvent."
- 9-digit organization numbers only, and it says so. No name-matching, no fuzzy search — this
is a deterministic lookup, so a wrong or malformed number fails cleanly as
BAD_FORMATinstead of guessing. - Misses are still rows, and rows are still free. A number that doesn't resolve comes back with
"found": false"and a plain-English reason, but is never billed. - Built for a list, not a lookup. Concurrency, keyword filtering, and column selection are all configurable inputs — feed in a few numbers or a few thousand.
Use cases
- KYB / vendor onboarding. Confirm a Norwegian counterparty is registered, solvent, and not under liquidation before you sign a contract or set up a payment relationship with them.
- Sales and lead enrichment. Attach legal form, industry code, and employee count to a list of Norwegian prospect organization numbers you already have from a CRM export or a scrape.
- Credit and risk screening. Batch-check bankruptcy and under-liquidation flags across a portfolio of Norwegian entities on a schedule, instead of checking them one at a time on the Brønnøysund website.
- Compliance data refresh. Re-verify VAT registration status and registered address for entities already sitting in your CRM, so stale records get caught before an audit does.
What you get
Every input produces exactly one row. These fields are always present:
| Field | Type | Description |
|---|---|---|
query | text | The organization number you submitted, unmodified |
found | boolean | true if a matching entity was found (and billed), false if not |
status | text | OK, NOT_FOUND, or BAD_FORMAT |
message | text | Plain-English reason for a miss (omitted when found is true) |
scrapedAt | ISO 8601 timestamp | When this row was fetched |
When found is true, these fields are also populated:
| Field | Type | Description |
|---|---|---|
organizationNumber | text | The 9-digit Brønnøysund organization number, normalized |
name | text | Registered legal name |
organizationFormCode | text | Legal form code, e.g. AS, ASA, ENK |
organizationFormDescription | text | Legal form spelled out, e.g. "Aksjeselskap" |
industryCode | text | Primary NACE industry code |
industryDescription | text | Industry description matching that code |
registrationDate | date | Date the entity was registered in Enhetsregisteret |
employeeCount | number | Employee count on file (can be null if not reported) |
vatRegistered | boolean | Whether the entity is registered in the VAT (MVA) register |
bankrupt | boolean | Bankruptcy flag |
underLiquidation | boolean | Under-liquidation flag |
address | object | { street, postalCode, city, municipality } — registered business address, falling back to postal address when no business address is on file |
website | text | Company website, when Brønnøysund has one on file (often null) |
Field names are stable across runs — this is what lets an AI agent or a Clay HTTP column read the schema once and keep working.
Price
$4 per 1,000 organization numbers, plus a $0.00005 start fee. Misses (found:false) are never charged.
That works out to $0.004 per found row on the FREE tier, dropping to $0.002 per found row on
Apify's GOLD tier — the actor-start fee is flat regardless of tier. 1,000 organization numbers
through this actor: ~$4 if every one is found, less if some aren't. The same 1,000 rows through
a credit-based enrichment platform: $80–$400. A miss — a number that isn't registered, or one
you typed wrong — still comes back as a dataset row with found: false, but you're never billed
for it.
How to use
- In the Apify Console. Open the actor page and click Start — the
organizationNumbersfield is already pre-filled with a working example. Results land in the run's dataset as soon as each item is found. - Via the API. Call it directly with a POST request — no Console needed once you have an API token:
curl "https://api.apify.com/v2/acts/accountable_eel~brreg-company-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \-X POST \-H "Content-Type: application/json" \-d '{"organizationNumbers":["923609016","984851006"]}'
- On a schedule. Save this actor as an Apify Task with the input you want, then add a Schedule (hourly, daily, weekly) so it runs on its own — no server of your own required.
- Paste one 9-digit organization number per line into
organizationNumbers, or pass an array of them via the API. - Turn on
testRunfor your first attempt — it caps the run at the first 5 numbers so you can check the shape of the output before spending on the full list. - Run the actor. One row comes back per number, in the same order you submitted them.
- If you only want rows that resolved, turn on
onlyFound— misses are dropped from the dataset entirely (and were never billed regardless). - Use
columnsto narrow the output to just the fields you need, andincludeKeywords/excludeKeywordsto filter rows by content (e.g. exclude anything withunderLiquidationin the text, or keep only a specific industry code).
Input
{"organizationNumbers": ["923609016","984851006"]}
One 9-digit Brønnøysund organization number per line. Accepted formats: 923609016, spaces and dashes are removed automatically.
{"organizationNumbers": ["923609016", "984851006"],"testRun": false,"onlyFound": false,"maxConcurrency": 5}
organizationNumbers is a list of 9-digit Norwegian organization numbers — spaces and
dashes are removed automatically. One dataset row is returned per number; rows with
"found": false are never charged. Turn on testRun to try your list against just the
first 5 numbers before running the full batch. Optional includeKeywords /
excludeKeywords filter rows by content, maxResults caps the run early, and columns
lets you pick which fields to return.
Sample output
| query | found | status | organizationNumber | name | organizationFormCode | organizationFormDescription | industryCode | industryDescription | registrationDate | employeeCount | vatRegistered | bankrupt | underLiquidation | address | website | scrapedAt |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 923609016 | true | OK | 923609016 | EQUINOR ASA | ASA | Allmennaksjeselskap | 06.100 | Utvinning av råolje | 1995-03-12 | 21239 | true | false | false | {"street":"Forusbeen 50","postalCode":"4035","city":"STAVANGER","municipality":"STAVANGER"} | www.equinor.com | 2026-08-31T06:10:16.580Z |
One row per organization number, for example:
{"query": "923609016","found": true,"status": "OK","organizationNumber": "923609016","name": "EQUINOR ASA","organizationFormCode": "ASA","organizationFormDescription": "Allmennaksjeselskap","industryCode": "06.100","industryDescription": "Utvinning av råolje","registrationDate": "1995-03-15","employeeCount": 21500,"vatRegistered": true,"bankrupt": false,"underLiquidation": false,"address": {"street": "Forusbeen 50","postalCode": "4035","city": "STAVANGER","municipality": "STAVANGER"},"website": "www.equinor.com","scrapedAt": "2026-08-21T10:00:00.000Z"}
Numbers that don't resolve still get a row ("found": false, "status": "NOT_FOUND" or
"BAD_FORMAT", with a plain-English message), so you always get one row per input —
but you're never charged for those.
Use it from Clay, n8n, Make, or an AI agent
This actor runs synchronously over plain HTTP — call it directly from a script, a workflow tool, or an AI agent, no Apify Console needed once you have an API token.
curl "https://api.apify.com/v2/acts/accountable_eel~brreg-company-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \-X POST \-H "Content-Type: application/json" \-d '{"organizationNumbers":["923609016","984851006"]}'
n8n. Add an HTTP Request node: Method POST, URL https://api.apify.com/v2/acts/accountable_eel~brreg-company-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>, Body Content Type JSON, JSON Body {"organizationNumbers":["923609016","984851006"]} (swap in an expression from an earlier node for a real value).
Clay. Add an "HTTP API" column: Method POST, URL https://api.apify.com/v2/acts/accountable_eel~brreg-company-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>, Body {"organizationNumbers":["{{organization number}}"]}, mapping the row's organization number into the organizationNumbers array.
MCP. In Claude, Cursor, or any MCP client with the Apify MCP server, ask for "Norway Company Registry Lookup | Apify" — the agent will find and run this actor.
Tips
- Run
testRun: trueon a new list first — it's free-ish (5 numbers) and confirms your input format before you commit a large batch. - Turn on
onlyFoundwhen you're feeding results straight into a CRM or Clay table and don't wantNOT_FOUNDrows cluttering the import. bankruptandunderLiquidationare separate flags — a company can beunderLiquidation: trueandbankrupt: false(voluntary winding-up is not the same as insolvency).employeeCountandwebsiteare both frequentlynull— not every entity reports employees to Brønnøysund, and many small entities have no website on file. Don't treat anullas an error.- If you already have organization numbers from another source (a CRM field, a scrape, an earlier
actor run), strip anything that isn't 9 digits before you submit —
BAD_FORMATrows are free but they're still a row you have to filter out downstream. industryCodefollows Norway's NACE classification, not NAICS or SIC — if you're filtering or joining against a US-sourced dataset, map the code rather than string-matching the description.- The
addressobject falls back from business address to postal address automatically, but a small number of entities (shell companies, some foundations) file neither — expect an occasionalnullthere even on an otherwise fully populated row.
vs. alternatives
| What it costs | What you get | Trade-off | |
|---|---|---|---|
This actor (brreg-company-lookup) | $0.004 per found row (FREE tier, less on paid tiers), $0.00005 actor start, nothing for a miss | One row per organization number — legal form, NACE industry code, registered address, employee count, VAT status, bankruptcy/liquidation flags | Norwegian organization numbers only, exact match — no company-name search, and it won't resolve a number that's typed wrong or belongs to a different country |
| Brønnøysund directly | Free | The same data, from the same source | It's the same source — this actor exists for the batch: thousands of numbers in, thousands of rows out, retries and rate limits handled, in the format your table already reads. One number, once? Use the portal. |
| Clay | $0.08–$0.40 per enriched row in credits, on top of a seat | A whole enrichment workspace — waterfalls across dozens of providers, plus the table and the sequencing around it | If you want one place that does everything and you're not counting rows, that's Clay. This is one column, priced per column, callable from Clay via its HTTP step. |
| Doing it yourself | Your time + handling Brønnøysund's response shapes (address falls back between two different fields, 404s serve no Content-Type header) and rate limits across a list | The same data | This actor absorbs the edge cases already found in src/target.js — the missing-header 404, the address fallback — so you don't rediscover them one failed request at a time |
Prices for third-party tools are their published list prices as of August 2026 and are not tracked here — check the vendor before relying on the comparison.
FAQ
What happens when an organization number isn't found?
You get a row with "found": false, "status": "NOT_FOUND", and a plain-English message. It
counts toward your dataset but not toward your bill — only rows with found: true are charged.
What if I submit something that isn't a valid organization number?
It's rejected before any request is made, returned as "status": "BAD_FORMAT", and not charged.
Spaces and dashes are stripped automatically (923 609 016 and 923-609-016 both normalize to
923609016), but anything that isn't 9 digits after that fails as BAD_FORMAT.
Are there rate limits?
maxConcurrency controls how many requests run in parallel (default 5) — set it lower if you want
to be gentler on Brønnøysund's API, or raise it for a large batch. The actor doesn't impose its own
cap beyond that; Brønnøysund's public API doesn't publish a documented rate limit, but very high
concurrency on a very large list is the thing most likely to trigger throttling on their end. If
you're running thousands of numbers and see failed requests climb, dropping maxConcurrency to 2
or 3 usually clears it up.
How fresh is the data?
Each row reflects what Enhetsregisteret returned at the moment the actor ran (scrapedAt records
that timestamp). Nothing is cached or stored between runs — if a company's status changes in
Brønnøysund's register, whether that's a new bankruptcy filing, an address change, or a VAT
deregistration, the next run picks it up. There's no lag between what the actor returns and what
the register currently shows.
Does this need proxies? No. Brønnøysund's API is public, unauthenticated, and not behind bot protection — the actor calls it directly.
Is this personal data, and does GDPR apply? The fields returned are entity-level — legal name, registered address, industry code, employee count, compliance flags — not data about named individuals. This actor doesn't return board members, signatories, or any other named-person fields, so there's no personal-data question to navigate on that front. It's public Norwegian company-register data either way, not scraped from a third-party site — the same records a Norwegian bank, landlord, or notary would pull to check a counterparty before signing anything with them.
What's the difference between organizationFormCode values I might see?
The most common are AS (private limited company), ASA (public limited company, like the
Equinor example above), ENK (sole proprietorship), and STI (foundation) — but Enhetsregisteret
covers dozens of legal forms, including associations and public-sector entities. organizationFormDescription spells out whichever code comes back, so you don't need to memorize the
list.
Can I schedule this to re-run on a list I already have? Yes — set it up as an Apify scheduled task with a saved input, and each run re-checks your list against the live register. There's no delta or "changed since last run" mode built in; every run re-fetches every number.
Can an AI agent call this directly? Yes, via the Apify MCP server — an agent asks for "Norway Company Registry Lookup | Apify" and can run it with a list of organization numbers, no separate integration code needed.
Does this cover anything outside Norway?
No. It only resolves entities registered in Norway's Enhetsregisteret. For Finnish entities, see
prh-company-lookup; for a single call that checks several national registries at once, see
company-registry-unified-lookup.