Romanian Registry Change Monitor — New Firms & Status Changes avatar

Romanian Registry Change Monitor — New Firms & Status Changes

Pricing

from $10.00 / 1,000 result records

Go to Apify Store
Romanian Registry Change Monitor — New Firms & Status Changes

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

Oaida Adrian

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

4 days ago

Last modified

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:

FieldMeaning
cuiCompany fiscal code (CUI)
company_nameRegistered company name
caenMatched CAEN code (version-resolved)
countyCounty (județ)
event_typeNEW_REGISTRATION / DEREGISTRATION / STATUS_CHANGE
status_beforePrevious status (null for new registrations)
status_afterNew status (null-able)
event_dateRegistration date (new) or dump date (status changes)
source_urlWhere 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

FieldTypeDefaultDescription
caenstring6201Target CAEN activity code. Version-equivalent codes matched automatically.
sincestringlast 30 daysReport only changes with event_date >= this date (YYYY-MM-DD).
countystringRestrict to one county (e.g. Cluj, Bucuresti). Empty = all.
outputstringjsonjson = one item per change; table = same records plus a human-readable summary field.
maxItemsint100Max change records emitted per run.
probeBudgetint1500Max CUI probes in the live layer per run.
frontierStartint55449500CUI anchor for the first live probe (see frontier note below).
useLiveLayerbooltrueEnable the cuiscan freshness probe.
useDumpLayerbooltrueEnable the official dump delta layer.
failOnUnreachableSourcesbooltrueFail the run (instead of exiting green with an empty dataset) when no configured source could be read at all. See Empty vs. unreadable below.
useProxybooltrueRoute 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.
proxyGroupsarray[]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"].
useResidentialProxyboolfalseForce 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.
proxyCountrystringOptional two-letter exit country for the proxy, e.g. RO (residential target). Empty = any.
proxyDiagnosticsboolfalseTroubleshooting: 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 SUCCEEDED with 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 UNREACHABLE status 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_show from Actor egress ended in ConnectTimeoutError (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:

AttemptResult
Control URL (api.ipify.org) through the datacenter proxyHTTP 200 in 0.34 s (exit IP logged) — the proxy itself works
data.gov.ro through the datacenter proxyReadTimeout at 25 s (tunnel established, no response)
data.gov.ro over plain HTTP through the same proxyReadTimeout at 60 s
data.gov.ro through two pinned datacenter sessionsProxyError

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.03s
Proxy pre-flight conclusion: proxy egress works ... but data.gov.ro does not answer
through 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=readable in every run above). New registrations keep flowing.
  • Dump layer (status changes / deregistrations) — needs an egress data.gov.ro accepts. Options, cheapest first:
    1. Nothing extra, no dump data: leave useProxy on and accept dump=UNREADABLE. The layer is then loud (degraded run + status message) instead of silently empty.
    2. Residential proxy (useResidentialProxy: true, optionally proxyCountry: "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.
    3. 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.

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 ApifyClient
client = 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_typecompanycuicountyevent_date
NEW_REGISTRATIONIMMERSIA S.R.L.554494152026-08-18
NEW_REGISTRATIONPIXELMAN GAMING S.R.L.55449288MUNICIPIUL BUCUREŞTI2026-08-18
NEW_REGISTRATIONDERBIES S.R.L.554492702026-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 same since date.
  • 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 since windows with a small probeBudget may 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 useProxy on, Apify's datacenter proxy still gets no answer (measured 2026-09-16), so STATUS_CHANGE / DEREGISTRATION records 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 reports readable: false with a reason, and the run finishes as degraded (status message) rather than green.