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
2 days ago
Last modified
Categories
Share
Romanian Registry Change Monitor (ONRC) — New Firms & Status Changes by CAEN
Daily change feed from the Romanian trade register (ONRC) for one CAEN code: new company registrations, deregistrations (radiere) and status changes such as insolvency or dissolution. Each change comes with the company's CUI, name, CAEN code, county and event date.
For: sales teams that want brand-new Romanian companies in their sector as leads, and risk teams watching a sector for insolvency or dissolution. Schedule it daily; each run returns only new changes.
Try it: {"caen": "6201", "since": "2026-08-12"} (software development, one-week window)
| Event | 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 |
Real output from a verified live run (Aug 2026, see "Worked example" below). All three matched CAEN 6210, the v3 equivalent of 6201.
Price: $0.01 per change record, plus a $0.01 run start at the default 1 GB memory. $10.01 per 1,000 changes in one run.
Running this on a schedule? A short review on the Apify Store helps others find it.
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
Standing state for this published Actor (decided 2026-09-16): option 1 — no
residential spend, no plan upgrade. The operator's own public store actor accepts
dump=UNREADABLE, live=readable with the loud degraded status message and the
proxy pre-flight diagnostics naming the blocker; that honest signal is deliberate
and must not be silenced. Option 2 remains available to anyone on a paid plan,
option 3 is a self-hosted path, not a dependency of this Actor.
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:
| Event | Price |
|---|---|
result (one per change record emitted) | $0.01 |
apify-actor-start (per run, per GB of memory) | $0.01 at the default 1 GB |
- 1,000 change records in one run: $10.01.
- A daily schedule costs $0.01 per day in start fees plus $0.01 per change it finds.
- If nothing is emitted, only the start fee is charged.
- The start fee scales with memory: a run raised to 4 GB starts at $0.04.
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.
Related Romanian company data tools
| Step | Tool | Input → output |
|---|---|---|
| 1. Find companies | Romanian Company Lookup by CUI/CIF | CUI or keyword → CUI, VAT status, J-number, CAEN, address, website |
| 2. Check the numbers | Romanian Financial Statements by CUI | CUI → turnover, net profit, assets, employees per year |
| 3. See their public contracts | Romanian Public Contracts Scraper | supplier CUI / keyword / CPV / authority → tenders, winners + winner CUI, RON values |
All of these tools return the company CUI, so results join on that field.
Running this on a schedule? A short review on the Apify Store helps others find it.