Romanian Registry Change Monitor — New Firms & Status Changes
Pricing
from $10.00 / 1,000 result records
Romanian Registry Change Monitor — New Firms & Status Changes
Monitors the Romanian company registry (ONRC) for new registrations, deregistrations and status flips in a target CAEN sector. Run daily and consume only the changes since a date. Emits cui, company_name, caen, county, event_type, status_before, status_after, event_date, source_url.
Pricing
from $10.00 / 1,000 result records
Rating
0.0
(0)
Developer
Oaida Adrian
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
4 days ago
Last modified
Categories
Share
Romanian Registry Change Monitor (ONRC) — CAEN-Sector Change Feed
Monitor the Romanian company registry (ONRC) for changes in a target CAEN activity sector: new registrations, deregistrations, and status flips (funcțiune / insolvență / dizolvare / lichidare / radiată / …). A scheduled monitor — run it daily or weekly and consume only what changed since a date, instead of re-pulling the whole registry.
Built for the recurring-revenue slot in the Romanian business-data niche: directory lookups are one-shot, a change feed is something customers schedule.
What it does
For the requested CAEN code (default 6201 — software development), the
actor emits one dataset item per change:
| Field | Meaning |
|---|---|
cui | Company fiscal code (CUI) |
company_name | Registered company name |
caen | Matched CAEN code (version-resolved) |
county | County (județ) |
event_type | NEW_REGISTRATION / DEREGISTRATION / STATUS_CHANGE |
status_before | Previous status (null for new registrations) |
status_after | New status (null-able) |
event_date | Registration date (new) or dump date (status changes) |
source_url | Where the record came from |
Plus source, caen_requested, and detected_at for provenance.
How it works — two layers
1. Live freshness layer (cuiscan.ro public API).
New registrations get sequentially-allocated CUI numbers, so the newest
firms sit at the top of the CUI range. The actor probes a CUI window
(default anchored just above the observed Aug-2026 frontier) and reports
firms whose declared CAEN matches the requested sector and whose
registration date is >= since. This is what makes since dates inside
the current month return records while the official dump lags.
2. Official dump delta layer (data.gov.ro monthly ONRC open data).
Every month ONRC publishes a full-registry snapshot (od_firme.csv,
od_caen_autorizat.csv, od_stare_firma.csv). The actor streams the
newest dump filtered to the target CAEN codes, diffs it against the
last-seen snapshot stored in the key-value store, and emits exactly the
changes — the authoritative source for STATUS_CHANGE and
DEREGISTRATION. Idempotent: a dump is processed once (keyed by dump id),
and when the newest dump predates since the layer is skipped entirely.
CAEN version aliasing. The registry migrated from CAEN v2 to v3;
"software la comandă" is 6201 in v2 and 6210 in v3 (same activity name
in the official n_caen.csv). The actor resolves the requested code to all
codes sharing its activity name across versions, so caen: 6201 also
matches v3-coded firms.
Input
| Field | Type | Default | Description |
|---|---|---|---|
caen | string | 6201 | Target CAEN activity code. Version-equivalent codes matched automatically. |
since | string | last 30 days | Report only changes with event_date >= this date (YYYY-MM-DD). |
county | string | — | Restrict to one county (e.g. Cluj, Bucuresti). Empty = all. |
output | string | json | json = one item per change; table = same records plus a human-readable summary field. |
maxItems | int | 100 | Max change records emitted per run. |
probeBudget | int | 1500 | Max CUI probes in the live layer per run. |
frontierStart | int | 55449500 | CUI anchor for the first live probe (see frontier note below). |
useLiveLayer | bool | true | Enable the cuiscan freshness probe. |
useDumpLayer | bool | true | Enable the official dump delta layer. |
failOnUnreachableSources | bool | true | Fail the run (instead of exiting green with an empty dataset) when no configured source could be read at all. See Empty vs. unreadable below. |
useProxy | bool | true | Route every data.gov.ro request (catalogue API + dump CSV) through Apify Proxy. Required in practice: direct Apify egress cannot reach data.gov.ro. See Reading data.gov.ro below. |
proxyGroups | array | [] | Proxy groups for the dump layer. Empty = auto (datacenter pool — included in every plan). Fill in only as a troubleshooting/upgrade step, e.g. ["RESIDENTIAL"]. |
useResidentialProxy | bool | false | Force the dump layer onto residential IPs (billed $8/GB, ≈$9.30 per processed dump, paid plans only). Use only if datacenter egress is refused and you need the dump. |
proxyCountry | string | — | Optional two-letter exit country for the proxy, e.g. RO (residential target). Empty = any. |
proxyDiagnostics | bool | false | Troubleshooting: the pre-flight also probes data.gov.ro through pinned exit IPs and over plain HTTP, and fetches a control URL, so the run log shows whether the proxy works and what the target does with that egress. |
Example input:
{"caen": "6201","since": "2026-08-12","output": "json","maxItems": 100}
Empty vs. unreadable (run-failure semantics)
An empty dataset has two possible meanings, and a scheduled monitor must never confuse them:
- Empty because nothing changed — the sources answered and had no matching
changes. The run exits
SUCCEEDEDwith a terminal status message naming which sources answered (0 change record(s); sources: dump=readable, live=readable). - Empty because nothing could be fetched — every enabled source was
unreachable (timeouts, 429s, a throttling datacenter egress, an empty resource
map on data.gov.ro). The run FAILS with a
SOURCE UNREACHABLEstatus message naming the reason for each layer. Downstream schedulers and alerting then see a red run instead of a plausible-looking "no changes".
If only one of two enabled layers is unreadable, the run still succeeds (the
other layer's data is real) but records a Degraded run status message.
Set failOnUnreachableSources: false to restore the old always-green behaviour
(not recommended for scheduled monitoring).
Reading data.gov.ro from Apify (egress block + proxy)
data.gov.ro (the ONRC open-data portal) does not serve Apify's direct egress. Measured 2026-09-16 on the published build:
- Every
package_showfrom Actor egress ended inConnectTimeoutError(30 s) — the connection is never established. - The same URLs answer in 0.1–0.2 s from an ordinary Romanian line, and the dump files stream at 2–15 MB/s there. So the portal is up; it is our egress that is refused.
The dump layer therefore runs through Apify Proxy (useProxy, on by
default). What was measured with it:
| Attempt | Result |
|---|---|
Control URL (api.ipify.org) through the datacenter proxy | HTTP 200 in 0.34 s (exit IP logged) — the proxy itself works |
data.gov.ro through the datacenter proxy | ReadTimeout at 25 s (tunnel established, no response) |
data.gov.ro over plain HTTP through the same proxy | ReadTimeout at 60 s |
data.gov.ro through two pinned datacenter sessions | ProxyError |
Datacenter proxy egress is not sufficient. The portal accepts the TCP
connection and then does not answer, i.e. it filters on the egress IP itself,
not on the protocol. Because that verdict is reached by a request that costs
nothing, the dump transfer is skipped once the pre-flight fails (reason
proxy-blocked): a blocked run finishes in seconds instead of streaming 1.16 GB
that cannot arrive. The run log states this explicitly:
Proxy pre-flight: control api.ipify.org via auto -> HTTP 200 in 0.34s (exit ip ...)Proxy pre-flight FAILED: data.gov.ro package_show(...) via auto -> ReadTimeout after 25.03sProxy pre-flight conclusion: proxy egress works ... but data.gov.ro does not answerthrough it — the block is on data.gov.ro's side, not in this Actor's proxy wiring.Source health: dump={'attempted': True, 'readable': False, 'reason': 'status=missing-resource ... proxy=auto', 'proxy': 'auto', 'proxy_check': {...}} live={'attempted': True, 'readable': True, ...}
What still works, and what it costs
- Live layer (cuiscan.ro) — unaffected, readable from Apify's own egress
(
live=readablein every run above). New registrations keep flowing. - Dump layer (status changes / deregistrations) — needs an egress
data.gov.ro accepts. Options, cheapest first:
- Nothing extra, no dump data: leave
useProxyon and acceptdump=UNREADABLE. The layer is then loud (degraded run + status message) instead of silently empty. - Residential proxy (
useResidentialProxy: true, optionallyproxyCountry: "RO"): the only Apify-side group with real consumer IPs. Cost: a full dump diff streams ~1.16 GB (od_caen_autorizat.csv≈ 412 MB,od_firme.csv≈ 662 MB,od_stare_firma.csv≈ 88 MB) at $8/GB, i.e. ≈$9.30 of proxy usage per new dump processed (at most once a month — re-runs on the same dump id transfer nothing). Residential has no available IPs on the Free plan; a paid plan is required. Datacenter IPs are included in every plan and are free at this scale, so keep the default unless you specifically need the dump. - Run the dump layer from an egress the portal trusts (a host in Romania, or any IP it serves) and feed the actor the resulting records — the portal is not the only ONRC consumer that can reach it.
- Nothing extra, no dump data: leave
Run time budget
Processing one new dump reads ~1.16 GB and parses ~24 M CSV rows, so allow a
longer run timeout: the dump budget is
min(900 s, remaining run time − 90 s), and a 300 s run therefore gets ~210 s.
A run that cannot finish the stream ends cleanly with status=budget — it never
persists a partial snapshot and never emits a partial diff.
Integrity guard (why a half-read dump is refused)
A truncated OD_FIRME.CSV would look like "these firms disappeared" and produce
a storm of false DEREGISTRATION records. Every stream therefore records whether
it finished (complete) and which column names it found; a stream that dies
mid-file, a deadline cut, or a renamed column yields
status=unreadable/budget and the snapshot is left untouched. Columns are
resolved by position from the header, with the ONRC spelling variants
(COD_CAEN_AUTORIZAT / COD_CAEN) accepted — and a column that is missing
entirely is an error, never a silent blank.
Frontier note (important for scheduling)
New companies get the next available CUI number, so the frontier moves
up over time. The actor keeps a frontier cursor in its named KV store:
the first run probes downward from frontierStart (default anchored just
above the observed Aug-2026 frontier) to cover the recent window; later
runs probe upward from the last-known frontier, catching only newly
allocated CUIs — efficient daily monitoring without re-probing history.
If the registry outgrows the default anchor (months from now), raise
frontierStart above the newest CUI you know, or clear the actor's KV
store to force a fresh downward sweep.
Output
One dataset item per change (see table above). Nothing is emitted when nothing changed in the window. Example:
{"cui": 55449288,"company_name": "PIXELMAN GAMING S.R.L.","caen": "6210","county": "MUNICIPIUL BUCUREŞTI","event_type": "NEW_REGISTRATION","status_before": null,"status_after": "funcțiune","event_date": "2026-08-18","source_url": "https://cuiscan.ro/api.php?action=company&cui=55449288","source": "cuiscan","caen_requested": "6201","detected_at": "2026-08-19T09:00:00.000000+00:00"}
Use cases
- Lead generation — new companies in a sector = fresh prospects (software shops registering this week, etc.).
- Insolvency / risk monitoring — status flips (funcțiune → insolvență) for a watchlist sector.
- Market intelligence — deregistrations and new entrants per CAEN.
Run it from the API
Trigger a monitor pass and get the changes back in one call:
curl -X POST "https://api.apify.com/v2/acts/darknezz~ro-registry-change-monitor/run-sync-get-dataset-items?token=YOUR_TOKEN" \-H "Content-Type: application/json" \-d '{"caen": "6201", "since": "2026-08-20", "maxItems": 100}'
Or from Python with the official SDK:
from apify_client import ApifyClientclient = ApifyClient("YOUR-APIFY-TOKEN")run = client.actor("darknezz/ro-registry-change-monitor").call(run_input={"caen": "6201", "since": "2026-08-20"})for item in client.dataset(run["defaultDatasetId"]).iterate_items():print(item["event_type"], item["company_name"], item["cui"])
Scheduling: the actor keeps a frontier cursor in its named KV store, so consecutive runs probe only newly allocated CUIs — attach a daily Apify Schedule and each run returns that day's new firms in your sector.
Worked example (verified live)
Trial input {"caen": "6201", "since": "2026-08-12"} (software sector, one
week window) returned three real new registrations:
| event_type | company | cui | county | event_date |
|---|---|---|---|---|
| NEW_REGISTRATION | IMMERSIA S.R.L. | 55449415 | — | 2026-08-18 |
| NEW_REGISTRATION | PIXELMAN GAMING S.R.L. | 55449288 | MUNICIPIUL BUCUREŞTI | 2026-08-18 |
| NEW_REGISTRATION | DERBIES S.R.L. | 55449270 | — | 2026-08-18 |
All matched CAEN 6210 (the v3 equivalent of the requested 6201 — the
version-aliasing layer working as designed). A second run minutes later
returned 0 records — the emitted-set prevented duplicates.
FAQ
Why did my caen: 6201 query return firms coded 6210? The registry
migrated from CAEN v2 to v3; "software la comandă" is 6201 in v2 and
6210 in v3. The actor resolves the requested code to every code sharing
its activity name, so you can use either.
Nothing came back — is it broken? A zero-item run is normal when no new
firms match your window. Also check since: if it is older than the newest
monthly dump, the dump layer skips (it can't satisfy an in-month window) and
only the live layer contributes.
When do deregistrations / status flips appear? They come from the official monthly ONRC dump (data.gov.ro), so they reflect the latest published snapshot — not intra-month flips. New registrations are live (cuiscan), typically same-week.
Do consecutive runs re-report the same firms? No. The emitted-set in the
named KV store (ro-registry-change-state) dedupes across runs with the
same since date, and the frontier cursor probes only new CUIs.
Can I watch a whole sector instead of one code? caen takes one code
(plus its version aliases). Run the actor per sector if you need several.
Idempotency & re-runs
- The emitted-set in the named KV store (
ro-registry-change-state) prevents duplicate emission across runs with the samesincedate. - The frontier cursor makes consecutive runs probe only new CUIs.
- The dump snapshot is keyed by dump id, so a dump is never processed twice.
Pricing
Pay per event — $0.01 per change record emitted (result primary event,
plus a one-time $0.01 actor-start; verified against the live pricing record
and the code's Actor.charge("result") call). Nothing emitted, nothing
charged beyond the actor start.
Limitations
- The live layer relies on cuiscan.ro's public API, which rate-limits
aggressive probing — the actor paces probes (~0.4 s) and budgets its
window per run. Very wide
sincewindows with a smallprobeBudgetmay not cover the whole window in one run; the frontier cursor covers the rest on subsequent runs. - Status changes and deregistrations come from the monthly ONRC dump, so they reflect the latest published dump, not intra-month flips.
- The official dump is published monthly; when it predates
since, only the live layer contributes records for that window. - data.gov.ro refuses Apify's egress: with
useProxyon, Apify's datacenter proxy still gets no answer (measured 2026-09-16), soSTATUS_CHANGE/DEREGISTRATIONrecords require an egress the portal accepts — see Reading data.gov.ro from Apify for the costed options. The run never hides this: the dump layer reportsreadable: falsewith a reason, and the run finishes as degraded (status message) rather than green.