CVR lookups in Python

CVR-API lets you fetch Danish company data in Python with a single HTTP request. You don't need an API key or an SDK. The standard library is enough.

Look up a company by CVR number

Call /api/v1/{cvr} and read the JSON response. This example only uses urllib from the standard library.

python
import json
import urllib.request

def get_company(cvr):
    url = f"https://apicvr.dk/api/v1/{cvr}"
    with urllib.request.urlopen(url, timeout=15) as res:
        return json.load(res)

company = get_company(24256790)
print(company["name"], company["zipcode"], company["city"])
print(company["industrydesc"], "-", company["companydesc"])

Search by company name

Fuzzy search finds companies even when the name is slightly misspelled. Each hit has name, cvr_number, industrycode and industrytext.

python
import json
import urllib.parse
import urllib.request

def search(name):
    url = f"https://apicvr.dk/api/v1/search/fuzzy/" + urllib.parse.quote(name)
    with urllib.request.urlopen(url, timeout=15) as res:
        return json.load(res)

for hit in search("novo nordisk")[:5]:
    print(hit["cvr_number"], hit["name"], "-", hit["industrytext"])

Handle errors

The API uses standard HTTP status codes, so you can act on them directly:

StatusMeaning
200The company was found. The body is JSON.
404No company has that CVR number. Body: {"detail": {"error": "NOT_FOUND"}}
422The CVR number isn't a number.
502The CVR register didn't answer. Try again shortly.
python
import json
import urllib.error
import urllib.request

def get_company(cvr):
    try:
        with urllib.request.urlopen(f"https://apicvr.dk/api/v1/{cvr}", timeout=15) as res:
            return json.load(res)
    except urllib.error.HTTPError as err:
        if err.code == 404:
            return None  # no company with that CVR number
        raise  # 422 = not a number, 502 = the CVR register did not answer

print(get_company(99999999))  # None

Owners, management and marketing protection

The full lookup includes legal owners with ownership share in ranges, and the current management.

python
company = get_company(24256790)

for owner in company["ejere"]:
    print(owner["name"], owner["ownership_range"])

for person in company["direktion"]:
    print(person["role"], person["name"])

if company["protected"]:
    print("Reklamebeskyttet - må ikke bruges til direkte markedsføring")
Always check protected before using the data for marketing. When it's true, the company has opted out of direct marketing.

Prefer requests?

python
import requests

res = requests.get("https://apicvr.dk/api/v1/24256790", timeout=15)
res.raise_for_status()
print(res.json()["name"])

Frequently asked questions

Do I need an API key in Python?

No. CVR-API needs no key and no account. A plain GET request is enough.

Which Python version is required?

The examples work on Python 3.6 and later, since they only use the standard library and f-strings.

Can I look up many companies at once?

Make one request per CVR number and keep the pace reasonable. If you need sustained heavy traffic, email [email protected].