# Germany LUCID Packaging Register Check (EPR) (`rastriq/germany-lucid-register-check`) Actor

- **URL**: https://apify.com/rastriq/germany-lucid-register-check.md
- **Developed by:** [Rastriq — Structured data from the world](https://apify.com/rastriq) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.80 / 1,000 registration checkeds

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

## Germany LUCID Packaging Register Check (EPR)

**LUCID Register Check** is a German packaging **EPR** (Extended Producer Responsibility, VerpackG) check. It looks up your own list of companies, VAT IDs or brands in Germany's public **packaging register LUCID** (ZSVR) and returns one clean row per registration: registration number, company, legal form, VAT ID, brands, packaging types, status and exit date. A weekly **monitor** mode tells you only what changed. It is a **LUCID packaging register check** for your own supplier, seller and brand lists.

> ### ⚠️ Not a replacement for the official register extract
>
> LUCID Register Check is a convenience check of the **public** registers. It does **not** replace the official **Registerauszug / ZSVR Registerabruf** that online marketplaces, fulfilment providers and other distributors must obtain to prove compliance. For legally binding checks, use the official channel of the register operator. Results can be incomplete or out of date: LUCID is updated once a day and the Actor reports the register's own "last updated" time in every row.

### What is LUCID Register Check?

Selling packaged goods in Germany requires the producer to be registered in the packaging register LUCID (VerpackDG). Marketplaces and retailers ask suppliers for proof, and compliance teams want to know quickly whether a supplier, brand or VAT number is listed.

LUCID Register Check automates the manual search on the public LUCID register, **one list item at a time**, politely (**at most 1 request per second, a single session, no concurrency**). It is built for **list checks**, not for downloading the registers: there is no "give me everything" mode and every run is limited in size.

#### What you get

| | |
|---|---|
| 🔎 **Check** | Look up VAT IDs, company names and brands. Exact and partial matches are labelled. Items with no match return a `not_found` row (VAT IDs, and names that include a legal form). |
| 🔔 **Monitor (delta)** | Re-check a saved list on a schedule (weekly is plenty). First run = `baseline` (everything in your list); later runs return only `new`, `changed` and `removed` registrations, and finish in seconds when LUCID has not been updated. |
| 🧭 **Discover** | Search one brand or company term, with a hard limit of 1,000 legal entities per run. |
| 🏢 **Companies only** | Sole traders and private individuals are always excluded (see below). |

#### Check vs monitor: what each mode returns and charges

| Mode | Kind | What you get | What is charged |
|---|---|---|---|
| **Check** | snapshot | Every match for your list, every run | `registration-check` per row (including `not_found` rows) |
| **Discover** | snapshot | Matches for one search term (up to 1,000) | `registration-check` per row |
| **Monitor** | delta | 1st run: the whole list as `baseline`. Later runs: only `new` / `changed` / `removed` registrations | 1st run: `registration-check` per row. Later runs: `registration-change` per changed row only. **Unchanged registrations are never charged**; a run on an unchanged register costs only the start fee |

### Use cases: LUCID packaging register check

**1. Verify marketplace sellers before onboarding** - *marketplace, platform and fulfilment compliance teams.*
Before you list a seller, check whether it is registered in LUCID. Run `check` with the seller's `vatIds` (and `companyNames` with the legal form). Read `status` (`registered`, `deregistered`, `not_found`), `registration_number`, `registration_date` and `market_exit_date`. You get a yes / no / expired answer per seller for your onboarding file. This is a quick pre-check; for proof use the official Registerauszug (see the notice above).

**2. EPR agencies and compliance consultancies** - *EPR service providers and advisors.*
Check a client's or prospect's whole list by VAT ID in one run. `not_found` rows show companies with no LUCID registration (a conversation to start); `deregistered` rows with `market_exit_date` show lapsed ones. You get a status sheet per client or a prospecting list with `vat_id`, `company_name` and `status`.

**3. Brand protection** - *brand owners and legal teams.*
Find out who registered your brand name. Put it in `brands` and read `company_name`, `brands`, `registration_number` and `match_type` (`exact` or `partial`). You see whether a distributor, licensee or an unknown party registers goods under your brand in Germany.

**4. Cross-border supplier due diligence** - *procurement and supply-chain teams.*
Check EU suppliers that ship to German customers: `vatIds` with a foreign prefix return `country_code`, `vat_id`, `registration_date` and `status`; the flag `no_eu_vat_id` marks registrations without an EU VAT ID. You get evidence for supplier files and a list of those that are not registered.

**5. Weekly monitor of your own list** - *compliance and risk teams.*
Switch to `monitor` and schedule it weekly. The first run is the `baseline`; later runs return only `new`, `changed` and `removed` registrations (`change_type`, `changed_fields`, `previous_values`), and a supplier that disappears from the register shows as `removed_from_register`. You get an alert instead of a manual re-check.

#### Recipe 1: check suppliers by VAT ID and name

```json
{
  "mode": "check",
  "vatIds": ["DE815499929", "FR12345678901"],
  "companyNames": ["HARIBO GmbH & Co. KG"],
  "includeDetails": true,
  "maxMatchesPerQuery": 5
}
```

#### Recipe 2: weekly monitor of a supplier and brand list

Run once to create the baseline, then schedule it weekly.

```json
{
  "mode": "monitor",
  "vatIds": ["DE815499929"],
  "companyNames": ["Nestlé Deutschland AG"],
  "brands": ["MAOAM"],
  "stateKey": "supplier-watchlist"
}
```

Reminder: LUCID Register Check covers **companies only** (private individuals and sole traders are never returned) and does **not** replace the official Registerauszug / ZSVR Registerabruf.

### Coverage

| Register | Operator | What is searched | Notes |
|---|---|---|---|
| **LUCID** (packaging, VerpackDG) | Zentrale Stelle Verpackungsregister (ZSVR) | VAT ID, company name, brand | Registration number, VAT ID, address city/postcode/country, brands, declared packaging types, registration and exit dates. Updated daily by the register. |
| WEEE / ElektroG directory (stiftung ear) | stiftung ear | - | **Not covered** in this version. |
| Battery register (BattDG) | stiftung ear | - | **Not covered** in this version. |

### Companies only - no private individuals

The public registers also list individual entrepreneurs, with personal names and home addresses. LUCID Register Check **never returns them**: a registration is only emitted when the registered name ends with a recognised **legal form** (GmbH, AG, UG (haftungsbeschränkt), KG, OHG, SE, GmbH & Co. KG, KGaA, eG, e.V., Ltd, LLC, Inc, S.L., S.A., S.A.S., B.V., N.V., S.r.l., S.p.A., Sp. z o.o., s.r.o., A/S, AB, Oy, AS and others). `e.K.` (registered sole merchant), `Inh.`, `GbR`, `PartG` and names without a legal form are treated as natural persons and dropped. Excluded rows are not output, not stored in the monitor state and not written to logs - the run summary only shows a counter. This filter has no off switch. Phone numbers and street addresses are never output.

If a company is excluded because its registered name has no recognisable legal form, you will not see it. That is intentional: the Actor prefers to miss a company than to publish a person.

### How to use LUCID Register Check

1. Open the Actor and keep **Mode = Check** (the pre-filled example looks up two well-known companies; **Max results** is pre-set to 5, which caps the first test at a few cents).
2. Paste VAT IDs, company names and/or brands (up to 200 items).
3. Click **Start**. Each item takes a few seconds (1 request per second; two more requests per match when brand and packaging details are on).
4. Open the **Output** tab or download the dataset (JSON, CSV, Excel).
5. To track changes, switch to **Monitor**, run once to create the baseline and add a weekly schedule.

**Tips**

- Use the official spelling: the LUCID search is accent-sensitive (`Nestlé`, not `Nestle`).
- Add the legal form to a company name (`HARIBO GmbH & Co. KG`) to get an exact match and a `not_found` row when nothing matches.
- Turn off **Include brands and packaging types** for the fastest yes/no check.

### What data you get

| Field | Description |
|---|---|
| `registration_number`, `company_name`, `legal_form` | LUCID registration number, registered name and detected legal form |
| `vat_id`, `country`, `country_code`, `city`, `postal_code` | VAT ID and registered address (city and postcode only, never the street) |
| `brands`, `brands_count` | Brands registered by the producer |
| `packaging_types` | Declared packaging types with `system_participation` (dual-system participation) |
| `authorised_representative` | When LUCID lists one |
| `registration_date`, `market_exit_date`, `status` | `registered`, `deregistered`, `not_found` or `removed_from_register` |
| `query_input`, `query_type`, `match_type` | Which list item produced the row, and whether the match is `exact` or `contains` |
| `source_url`, `source_updated_at`, `checked_at` | Source page, the register's own last-update time and the time of your run |
| `first_seen_at`, `last_seen_at`, `change_type`, `changed_fields`, `previous_values` | Monitor mode: what changed since your last run |
| `quality_flags` | `partial_match`, `not_found`, `no_eu_vat_id`, `deregistered`, `brands_truncated`, `details_unavailable`, `no_packaging_info` |
| `region`, `equipment_types` | Reserved, always `null` in this version |

### Input

| Field | Type | Description |
|---|---|---|
| `mode` | enum | `check` (default), `monitor`, `discover` |
| `vatIds` | array | EU VAT IDs (LUCID only) |
| `companyNames` | array | Company names, partial names allowed |
| `brands` | array | Brand names registered in LUCID |
| `searchTerm` | string | Discover mode: one term of at least 3 characters |
| `includeDetails` | boolean | Brands and packaging types (LUCID). Default on |
| `maxMatchesPerQuery` | integer | Best N matches per list item, exact first. Default 10, max 50 |
| `maxItems` | integer | Row limit and spending cap (pre-filled 5; 0 = no limit; discover: default 100, max 1,000) |
| `stateKey` | string | Optional name for a monitor stream |

### Output example

Real row from a check run (long texts shortened here):

```json
{
  "register": "lucid",
  "registration_number": "DE2755553072093",
  "company_name": "HARIBO GmbH & Co. KG",
  "legal_form": "GmbH & Co. KG",
  "vat_id": "DE815499929",
  "country": "Deutschland",
  "country_code": "DE",
  "city": "Grafschaft",
  "postal_code": "53501",
  "region": null,
  "brands": [
    "HARIBO",
    "MAOAM",
    "PANULI",
    "DUNHILLS",
    "RICQLÈS"
  ],
  "brands_count": 5,
  "packaging_types": [
    {
      "system_participation": true,
      "description": "Verkaufs- und Umverpackungen, Primärproduktionsverpackungen sowie T..."
    },
    {
      "system_participation": false,
      "description": "Transportverpackungen, die NICHT nach § 7 Absatz 1 Satz 1 VerpackDG..."
    },
    {
      "system_participation": false,
      "description": "Wiederverwendbare Verpackungen nach Artikel 11 der Verordnung (EU) ..."
    }
  ],
  "equipment_types": null,
  "authorised_representative": null,
  "registration_date": "2019-01-01",
  "market_exit_date": null,
  "status": "registered",
  "query_input": "HARIBO GmbH & Co. KG",
  "query_type": "name",
  "match_type": "exact",
  "source_url": "https://oeffentliche-register.verpackungsregister.org/Producer",
  "source_updated_at": "2026-10-24T01:10",
  "quality_flags": [],
  "checked_at": "2026-10-24T20:17:10Z",
  "first_seen_at": "2026-10-24T20:17:10Z",
  "last_seen_at": "2026-10-24T20:17:10Z",
  "change_type": null,
  "changed_fields": [],
  "previous_values": null
}
```

`status` is `registered`, `deregistered` (an exit date exists; LUCID keeps exited producers for three more years), `not_found`, or `removed_from_register` (monitor). `quality_flags` marks things like `partial_match`, `no_eu_vat_id`, `brands_truncated`, `deregistered` - rows are flagged, never silently dropped.

### Pricing

Pay per event. Tier discounts: Silver -15 %, Gold and above -30 % (Free plan +15 %).

| Event | Price (Bronze) |
|---|---|
| `registration-check` - one result row in check, discover or a monitor baseline (including `not_found` rows) | $4.00 / 1,000 |
| `registration-change` - one new / changed / removed registration in monitor | $6.00 / 1,000 |
| Actor start | $0.02 per run |

Only result rows are billed (check, discover and the first monitor run: `registration-check`; later monitor runs: `registration-change` for changed rows only). Unchanged registrations in monitor mode are free. A monitor run on an unchanged LUCID register finishes after one request and costs only the start fee. The pre-filled example (2 companies) costs about $0.03; checking 100 suppliers costs about $0.42. **Max results** caps what a run can bill.

### Responsible use and limits

- At most **1 request per second**, one session, no concurrency, no proxies, no circumvention. If a register shows a captcha, a block or an error rate above 5 % the run stops and tells you why.
- Lists are limited to 200 items per run and discover to 1,000 rows. The Actor is designed for checking your own suppliers and brands, not for building a copy of the registers.
- Register data is published by law. LUCID Register Check is **not affiliated with, endorsed by or operated by** ZSVR. Source attribution: *Zentrale Stelle Verpackungsregister (ZSVR), LUCID public register*. Check the register's terms of use for your use case.
- Not legal advice. Use the official register extract for binding proof.

### FAQ

**Does LUCID Register Check replace the Registerauszug?** No. Marketplaces and fulfilment providers must obtain the official extract/Registerabruf; this Actor is a quick public-register check.

**Why is a company I know missing?** Its registered name may have no recognisable legal form (it is excluded as a possible individual), be spelled differently (accents), or have left the register more than three years ago.

**Can I download the whole register?** No. There is deliberately no such mode.

**Can I disable the companies-only filter?** No.

**How often is the data updated?** LUCID publishes once a day; each row carries the register's own timestamp in `source_updated_at`. For monitoring, a weekly schedule is plenty.

**Is it legal to use this data?** The LUCID register is public by law (VerpackDG). The Actor reads only the public search pages, returns companies only (never private individuals) and does not circumvent any protection. You remain responsible for how you use the data; see *Responsible use and limits*.

**Where is monitor state kept?** In a named key-value store (`de-epr-state`) in your own Apify account; it holds the last result per registration so the next run can compare. You can delete it at any time to start a new baseline.

**Do I need proxies or an account?** No. The Actor needs no proxy, login or API key.

**Why does a monitor run return nothing?** Either LUCID has not changed since your last run (the run ends free) or nothing in your list changed. Check `RUN_SUMMARY` in the run's key-value store for the status and counts.

Built by **Rastriq** - reliable data from official registers. Questions or feature requests: use the Actor's Issues tab.

# Changelog

This Actor's version history is a separate document: https://apify.com/rastriq/germany-lucid-register-check/changelog.md

# Actor input Schema

## `mode` (type: `string`):

<b>Check</b> (default when empty): look up the items of your list and return the matching registrations; items with no match return a <code>not_found</code> row (VAT IDs and names that include a legal form).<br><b>Monitor</b>: same lookup on a saved list, but returns only <i>changes</i> since your last run (the first run returns everything as <code>baseline</code>). Schedule it weekly.<br><b>Discover</b>: search by one term (brand or company name) with a low result limit.

## `vatIds` (type: `array`):

EU VAT numbers, e.g. <code>DE815499929</code>. Spaces and dots are ignored. Check / monitor modes.

## `companyNames` (type: `array`):

Company names, e.g. <code>HARIBO GmbH & Co. KG</code>. Partial names also match (flagged <code>partial_match</code>). Including the legal form (GmbH, AG, Ltd…) makes a <code>not_found</code> row possible when nothing matches. Check / monitor modes.

## `brands` (type: `array`):

Brand names registered by producers in LUCID, e.g. <code>MAOAM</code>. Check / monitor modes.

## `searchTerm` (type: `string`):

One brand or company-name term, at least 3 characters, no wildcards. Returns up to <i>Max results</i> legal entities (hard limit 1,000). Discover mode only.

## `includeDetails` (type: `boolean`):

Fetches each match's brands and declared packaging types (two extra requests per match, so the run is slower). The price per row is the same either way. Turn off for the fastest yes/no check.

## `maxMatchesPerQuery` (type: `integer`):

A generic name can match many registrations. Keep the best <i>N</i> per item (exact matches first). Default 10, maximum 50.

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

Stop after this many rows (0 = no limit; in discover mode 0 means 100, and the maximum is 1,000). Each row is billed, so this is also your spending cap. Pre-filled with 5 so a first test costs a few cents.

## `stateKey` (type: `string`):

Optional. Monitor mode remembers each list under a name derived from the list itself, so editing the list starts a new stream. Set a name (e.g. <code>supplier-watchlist</code>) to keep one stream while you edit the list. Monitor mode only.

## Actor input object example

```json
{
  "mode": "check",
  "vatIds": [],
  "companyNames": [
    "HARIBO GmbH & Co. KG",
    "Miele & Cie. KG"
  ],
  "brands": [],
  "includeDetails": true,
  "maxMatchesPerQuery": 10,
  "maxItems": 5
}
```

# Actor output Schema

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

No description

## `runSummary` (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 = {
    "mode": "check",
    "vatIds": [],
    "companyNames": [
        "HARIBO GmbH & Co. KG",
        "Miele & Cie. KG"
    ],
    "brands": [],
    "maxItems": 5
};

// Run the Actor and wait for it to finish
const run = await client.actor("rastriq/germany-lucid-register-check").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 = {
    "mode": "check",
    "vatIds": [],
    "companyNames": [
        "HARIBO GmbH & Co. KG",
        "Miele & Cie. KG",
    ],
    "brands": [],
    "maxItems": 5,
}

# Run the Actor and wait for it to finish
run = client.actor("rastriq/germany-lucid-register-check").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 '{
  "mode": "check",
  "vatIds": [],
  "companyNames": [
    "HARIBO GmbH & Co. KG",
    "Miele & Cie. KG"
  ],
  "brands": [],
  "maxItems": 5
}' |
apify call rastriq/germany-lucid-register-check --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,rastriq/germany-lucid-register-check"
        }
    }
}
```

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/YccILnIJJHrsNAgmD/builds/yflrkrROfOsblnoK9/openapi.json
