Denmark Restaurant Inspections: Smiley Food Safety
Pricing
$2.00 / 1,000 food business units
Denmark Restaurant Inspections: Smiley Food Safety
Danish restaurant and food business inspection results from the Fødevarestyrelsen Smiley food safety scheme: up to four inspections per business, result labels, CVR, P-number, address and industry. Filter by postal code or result, or get only changed units. No API key needed.
Pricing
$2.00 / 1,000 food business units
Rating
0.0
(0)
Developer
Mikkel Jeppesen Juhl
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
Get Danish restaurant and food safety inspection results as clean JSON. The actor reads the open Smiley file that Fødevarestyrelsen publishes on findsmiley.dk. It returns one row per food business unit with its latest four inspections, ISO dates, English result labels, CVR and P-number, address, industry and the advertising protection flag.
The file covers about 59,000 restaurants, shops, bakeries, canteens, wholesalers and transport firms. You can filter it by postal code, city, industry, business type, CVR number, latest result and inspection date. You can also run the actor on a schedule and get only the units that changed since the last run, such as a new inspection or a new sour smiley.
Use cases
- Export Danish restaurant inspection results by postal code or city.
- Monitor new sour smileys and new inspections on a schedule with change detection.
- Look up every food business of a company by CVR number.
- Build food safety datasets for research, insurance, delivery platforms or local news.
What you get
| Field | Meaning |
|---|---|
smileyId | Fødevarestyrelsen's id for the unit, also the findsmiley.dk page number |
cvr | Danish CVR number of the owner, 8 digits. Missing for about 2% of units |
pNumber | Production unit number (P-nummer). Missing for about 3% of units |
name, address, postalCode, city | Unit name and address as registered with Fødevarestyrelsen |
businessType | retail (detail, sells to consumers) or wholesale (engros) |
smileyIndustry | Industry group on findsmiley.dk, in Danish, for example "Dagligvareforretninger" |
fvstIndustryCode, fvstIndustry | Fødevarestyrelsen's finer industry code and name |
latestResult | Result of the latest inspection, 1 to 4, or null with no inspection yet |
latestResultLabel | The result in English, see the table below |
latestSmiley | happy, straight or sour for retail units, null for wholesale |
latestInspectionDate | Date of the latest inspection, YYYY-MM-DD |
worstRecentResult | Highest result among the published inspections |
inspectionCount | How many inspections the file holds for the unit, 0 to 4 |
inspections | Up to four inspections, newest first, each with date, result and resultLabel |
advertisingProtected | true when the unit is flagged with reklamebeskyttelse. Always present |
findSmileyUrl | The unit's page on findsmiley.dk with the full inspection reports |
changeType | In change mode: new, changed or removed. Null otherwise |
changedParts | In change mode: inspections, details and or advertisingProtection |
previousLatestResult, previousLatestInspectionDate | In change mode: the values in the previous snapshot |
Result codes
| Code | Danish | English | Retail smiley |
|---|---|---|---|
| 1 | Ingen anmærkninger | No remarks | Happy |
| 2 | Indskærpelse | Warning | Straight mouth |
| 3 | Påbud, forbud eller tvangsbøder | Order, ban or daily fines | Straight mouth |
| 4 | Bødeforlæg, politianmeldelse, karantæne, autorisation eller registrering frataget | Fine, police report, quarantine, or approval or registration withdrawn | Sour |
A null result means the unit has not been inspected yet, or sits in the lowest risk group and is rarely inspected. Fødevarestyrelsen publishes a result before appeals end and before a fine is final, so a 4 is not a final verdict. Findsmiley.dk can also withdraw a report, and the unit's inspections then move up a slot.
Input
{"postalCodes": ["1000-2999", "8000"],"cities": ["Aarhus C"],"smileyIndustries": ["Restauranter, kantiner, takeaway, værtshuse m.fl."],"businessTypes": ["retail"],"cvrNumbers": ["35954716"],"latestResults": ["2", "3", "4"],"inspectedSince": "2026-01-01","excludeAdvertisingProtected": false,"onlyChangedSinceLastRun": false,"snapshotName": "default","includeRemoved": true,"maxItems": 1000,"sourceFormat": "xlsx"}
- Every filter is optional. Filters combine with AND. Values inside one filter combine with OR.
postalCodestakes single codes or ranges such as1000-2999.latestResultstakes1,2,3,4andnone.cvrNumbersreturns every unit the company owns. A supermarket chain owns over 1,000 units.sourceFormatpicks the 7 MB Excel file or the 60 MB XML file. They hold the same data.
Change detection
Turn on onlyChangedSinceLastRun and schedule the actor, for example daily. The first run saves a snapshot of the whole file in a named key-value store (dk-smiley-snapshots) and outputs nothing. Each later run compares the file with the snapshot and outputs only:
newunits that were not in the last snapshot,changedunits with a new inspection, a withdrawn inspection, new details or a changed advertising flag,removedunits that left the file. Removed rows are free.
Use one snapshotName per schedule. Your filters apply to the output, and the snapshot always covers the whole file, so you can change filters between runs. Fødevarestyrelsen rebuilds the file more than once a day.
Advertising protection (reklamebeskyttelse)
About 40% of the units carry advertisingProtected: true. The flag mirrors the CVR register's reklamebeskyttelse. A company sets it in CVR to say it does not want direct marketing. Under section 19 of the Danish CVR Act, a private company must not use CVR data about a protected unit for direct marketing, and anyone who passes on its contact data must mark it as protected. That is why the flag is in every row.
If you buy this data, you must not use it to direct-market units with advertisingProtected: true. That covers mail, phone calls, visits and any other sales approach built on this data. Separate rules apply to everyone: the Danish Marketing Practices Act section 10 bans unsolicited email and SMS marketing without prior consent, and the GDPR applies when a unit is a sole proprietorship named after a person. Set excludeAdvertisingProtected to drop protected units from the output. This is not legal advice. You are responsible for how you use the data.
Source, terms and no endorsement
Source: Fødevarestyrelsen (the Danish Veterinary and Food Administration), Smiley data from findsmiley.dk, downloaded from https://pub.fvst.dk/publikationer/Smileydata.xlsx or .xml on each run. Fødevarestyrelsen publishes the data under the Danish terms for reuse of public data, with four extra conditions: name Fødevarestyrelsen as the source, do not use its logo, any smiley shown for a single business must match its current smiley, and follow the design rules for the smiley symbols. If you show smiley symbols to others, show the current result and link to findSmileyUrl.
The actor renames the fields to English, converts dates to ISO format, adds result labels and computes latestSmiley, worstRecentResult and inspectionCount. Fødevarestyrelsen does not endorse or support this actor. The official results are the ones on findsmiley.dk.
Limits of the source
- Only the latest four inspections per unit are published, and nothing from before 24 January 2012.
- The file has no inspection report text. Read the reports on findsmiley.dk.
- Units appear by production site. Chains appear once per shop and department.
- The file has no email or phone data.
Run it locally
No Apify account is needed. You need uv.
cd apps/apify-dk-smiley-inspectionsuv sync./run_local.sh input.example.jsonuv run python test/coverage.py storage/datasets/defaultuv run python -m test.test_filters
Set SMILEY_SOURCE_FILE=/path/Smileydata.xml to read a saved file in place of the download. Run stats land in storage/key_value_stores/default/RUN_STATS.
Pricing
Pay per event: 0.002 USD per unit row (2 USD per 1,000). Removed rows in change mode are free. No start fee. A daily change run on all of Denmark returns about 150 rows on a weekday, since Fødevarestyrelsen inspects about 150 units a day.