# Diario Oficial Chile Scraper & Monitor (`stefano_seggio/diario-oficial-cl-monitor`) Actor

Extracts todays edition of Chile Diario Oficial (official gazette): laws, decrees and resolutions with full hierarchy (branch, ministry, agency) and direct PDF links per publication.

- **URL**: https://apify.com/stefano\_seggio/diario-oficial-cl-monitor.md
- **Developed by:** [Stefano Seggio](https://apify.com/stefano_seggio) (community)
- **Categories:** Lead generation
- **Stats:** 2 total users, 1 monthly users, 60.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Diario Oficial Chile Scraper & Monitor — Apify Store Overview

**Actor:** `stefano_seggio/diario-oficial-cl-monitor` (ID: `qfBeEKuLfYUw9UOuW`)
**Store URL:** https://apify.com/stefano\_seggio/diario-oficial-cl-monitor
**Version:** 2.0

***

### Executive Summary & Business Use Case

The Diario Oficial Chile Scraper & Monitor extracts today's edition of **Chile's Diario Oficial** — the country's official government gazette, published at `diariooficial.interior.gob.cl` — pulling every law, decree and resolution listed that day with its full institutional hierarchy (branch of government, ministry, sub-agency) and a direct link to the source PDF. The actor was built after a technical audit (2026-09-04) confirmed no existing Apify actor covered this source: Mexico's DOF and the Colombia/Paraguay procurement systems already had coverage from other developers, but Chile's gazette did not. It ships with an optional delta mode that returns only publications that are genuinely new or corrected since an earlier run the same day, so it can be scheduled intraday without re-delivering the same entries.

Because the source is a legal-publication registry rather than a commercial listing or tender board, the realistic use cases sit squarely in regulatory monitoring rather than pricing or inventory analysis — there is no monetary-value field anywhere in this dataset, so use cases are framed around *what changed and who published it*, not *what it's worth*. Three concrete examples: a **legal or compliance team** at a company operating in Chile watches `ministerio` and `organismo` for its sector (e.g. fisheries, mining, telecom) to catch new resolutions affecting its operations and route them to the right internal owner using `event_type=NEW_LISTING`; a **law firm or regulatory consultancy** tracks specific publications over time and uses `event_type=UPDATED` to know the moment a *fe de erratas* (correction) is re-published under the same CVE, so it can re-check the amended text before advising a client; and a **market-research or policy-analytics team** aggregates `rama`, `ministerio` and `seccion` across runs to build trend views of regulatory activity by government branch and agency.

What the actor deliberately does *not* claim is also part of its value proposition: a published legal notice in this domain is a permanent public record — it is never "adjudicated," "closed," or withdrawn the way a tender or licence might be — so the dataset has no status-change or closure event, and the documentation says so explicitly rather than forcing a generic lifecycle model onto a domain that doesn't have one.

### Technical Features & V2 Architecture Highlights

This actor ships with **named key-value-store cross-run delta persistence**: per its own `input_schema.json`, the `onlyNew` flag returns "only publications that are new or amended (a correction re-published under the same CVE) since a prior run today, tracked in a named key-value store scoped to this actor." In practice this means the actor remembers what it has already seen (keyed by `record_id`) across scheduled runs on the same day, so a run at 9am and a run at 3pm against the same edition won't re-deliver identical entries — only genuinely new listings or corrected ones.

The **real `event_type` values this actor emits are `NEW_LISTING`, `UPDATED`, and `UNCHANGED`** (the last one only surfaces when `onlyNew` is off, per `dataset_schema.json`'s own description: *"NEW\_LISTING (never seen before), UPDATED (a correction to a known entry) or UNCHANGED (only when Only new records is off)."*). This is a deliberately narrower set than the generic NEW\_LISTING/UPDATED/CLOSED pattern used elsewhere in the fleet: **there is no `CLOSED` or `STATUS_CHANGE` event in this actor at all.** Per its own `AGENTS.md`, this was a considered decision, not an oversight — "this domain has no status or lifecycle concept at all — the fleet's usual STATUS\_CHANGE/CLOSED categories were considered and explicitly NOT built here... A published law, decree or resolution is a permanent public record; it does not get 'adjudicated' or 'closed' the way a tender does. The one real thing that CAN happen to a published entry is a correction (a *fe de erratas*) re-published under the same CVE with amended text — that is `UPDATED`."

The `onlyNew` boolean (default `false`) is the actor's delta-mode switch. When `true`, only records flagged `NEW_LISTING` or `UPDATED` are delivered (narrowed further by the `eventTypes` array, which defaults to both values); when `false`, every entry from the resolved edition is pushed, including ones already seen (`UNCHANGED`). The companion `is_new` boolean field records, independent of the event-type gate, whether that specific `record_id` was already present in the persisted seen-set when the run started.

On the **dataset schema itself**: `dataset_schema.json` for this actor documents **15 fields** (`rama`, `ministerio`, `organismo`, `descripcion`, `pdfUrl`, `cve`, `seccion`, `edicion`, `fecha`, `scrapedAt`, `record_id`, `event_type`, `is_new`, `source_url`, `contentHash`) — this actor's own schema does not confirm an 18-field structure, so this overview reports the actual count rather than the fleet's usual figure.

Two more real, source-specific engineering facts worth surfacing to a technical buyer: this actor **does not use Crawlee's `CheerioCrawler`** — a live audit found the site serves a real ~22KB page with the full data table to a plain `fetch()` call, but a ~6KB JS bot-check stub (no table) to `got-scraping` (CheerioCrawler's default HTTP client) at the same URL, same machine, same moment. The actor is built on native `fetch()` with its own exponential-backoff retry logic instead. And `record_id` uses the source's own CVE (*Código de Verificación Electrónica*) when the link text matches the expected pattern, falling back to a `sha1` content hash (`seccion|edicion|descripcion|pdfUrl`) on the disclosed edge case where it doesn't.

### Input Schema & JSON Configuration Example

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `sections` | array (enum, select) | `["normas_generales"]` | Which sections of the edition to fetch. Not every section publishes content every day - a section with nothing that day returns 404 from the source and is skipped, not treated as an error. Allowed values: `normas_generales`, `avisos_destacados`, `marcas_patentes`, `normas_particulares`, `publicaciones_judiciales`, `empresas_cooperativas`, `bom`. |
| `maxItems` | integer | `300` | Hard cap on the number of publications returned this run, across all selected sections. |
| `onlyNew` | boolean | `false` | Return only publications that are new or amended (a correction re-published under the same CVE) since a prior run today, tracked in a named key-value store scoped to this actor. Most useful re-running the same day's edition on a schedule to catch late additions/corrections. There is no CLOSED or status-change event in this domain - a published legal notice is never withdrawn or 'closed', it is a permanent public record. |
| `eventTypes` | array (enum, select) | `["NEW_LISTING", "UPDATED"]` | Which kinds of change to deliver when 'Only new records' is on (ignored, everything delivered, when it is off). NEW\_LISTING = never seen before. UPDATED = same CVE (or identity), the content changed - a correction. Allowed values: `NEW_LISTING`, `UPDATED`. |

```json
{
  "sections": ["normas_generales", "marcas_patentes"],
  "maxItems": 150,
  "onlyNew": true,
  "eventTypes": ["NEW_LISTING", "UPDATED"]
}
```

### Output Dataset Sample & Data Dictionary

| Field | Type | Description |
| --- | --- | --- |
| `rama` | string | null | Branch of government, e.g. PODER EJECUTIVO |
| `ministerio` | string | null | Ministry or top-level agency |
| `organismo` | string | null | Sub-agency, e.g. a Subsecretaria |
| `descripcion` | string | The publication entry text |
| `pdfUrl` | string | null | Direct link to the official PDF |
| `cve` | string | null | Codigo de Verificacion Electronica |
| `seccion` | string | Which section this entry came from |
| `edicion` | string | Edition number |
| `fecha` | string | Edition date, DD-MM-YYYY |
| `scrapedAt` | string | ISO timestamp of extraction |
| `record_id` | string | The CVE when present, otherwise a content hash - see AGENTS.md. |
| `event_type` | string | NEW\_LISTING (never seen before), UPDATED (a correction to a known entry) or UNCHANGED (only when Only new records is off). |
| `is_new` | boolean | True if this id was not in the persisted seen-set when this run started. |
| `source_url` | string | The publication's own PDF link when present, otherwise the shared section page. |
| `contentHash` | string | sha1 fingerprint used to detect UPDATED (a correction) between runs. |

```json
{
  "rama": "PODER EJECUTIVO",
  "ministerio": "MINISTERIO DE ECONOMIA, FOMENTO Y TURISMO",
  "organismo": "Subsecretaria de Pesca y Acuicultura",
  "descripcion": "Extracto de resolucion exenta numero 2.092, de 2026.- Modifica resolucion N 159 exenta, de 2026",
  "pdfUrl": "https://www.diariooficial.interior.gob.cl/publicaciones/2026/09/04/44542/01/2865015.pdf",
  "cve": "2865015",
  "seccion": "normas_generales",
  "edicion": "44542",
  "fecha": "04-09-2026",
  "scrapedAt": "2026-09-04T16:16:42.538Z",
  "record_id": "2865015",
  "event_type": "NEW_LISTING",
  "is_new": true,
  "source_url": "https://www.diariooficial.interior.gob.cl/publicaciones/2026/09/04/44542/01/2865015.pdf",
  "contentHash": "a1b2c3d4e5f6789012345678901234567890abcd"
}
```

### Multi-language Integration Snippets

#### cURL

```bash
curl "https://api.apify.com/v2/acts/stefano_seggio~diario-oficial-cl-monitor/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{
    "sections": ["normas_generales"],
    "maxItems": 150,
    "onlyNew": true,
    "eventTypes": ["NEW_LISTING", "UPDATED"]
  }'
```

#### Python (apify-client)

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_TOKEN")

run_input = {
    "sections": ["normas_generales"],
    "maxItems": 150,
    "onlyNew": True,
    "eventTypes": ["NEW_LISTING", "UPDATED"],
}

run = client.actor("stefano_seggio/diario-oficial-cl-monitor").call(run_input=run_input)

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(f"[{item['event_type']}] {item['ministerio']} - {item['descripcion']}")
```

#### Node.js (apify-client)

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });

const runInput = {
    sections: ['normas_generales'],
    maxItems: 150,
    onlyNew: true,
    eventTypes: ['NEW_LISTING', 'UPDATED'],
};

const run = await client.actor('stefano_seggio/diario-oficial-cl-monitor').call(runInput);

const { items } = await client.dataset(run.defaultDatasetId).listItems();

for (const item of items) {
    console.log(`[${item.event_type}] ${item.ministerio} - ${item.descripcion}`);
}
```

### Pricing Model Explanation

This actor is pay-per-event, with platform usage included:

| Event | Price | What it means here |
| --- | --- | --- |
| `result` | $0.003 / record | Charged once per dataset item pushed. There is no second, cheaper tier for this actor - a gazette entry has no detail/summary distinction, because every publication row is already fully parsed inline from the edition's hierarchical table (branch, ministry, agency, description and PDF link all come from the same pass), so there's no "listing-only" vs "full detail" split to price differently. Every record that reaches the dataset costs the same. |
| `apify-actor-start` | $0.00005 / run | Charged once per run, regardless of how many sections are selected or how many records are returned. |

**Delta mode and billing:** when `onlyNew` is set to `true`, the actor only pushes dataset items for entries that are `NEW_LISTING` or `UPDATED` (further narrowed by `eventTypes`). An entry that is already known and unchanged is not delivered at all — it is not pushed as an `UNCHANGED` record and then charged at $0, it is simply never created as a dataset item in the first place, so it is never a chargeable `result` event. This is what makes scheduling the actor intraday economical: re-running the same day's edition every few hours to catch late additions or corrections only bills for what actually changed, not for re-confirming everything that didn't.

***

*Sources for this overview: `.actor/actor.json`, `.actor/input_schema.json`, `.actor/dataset_schema.json`, `.actor/output_schema.json`, `README.md`, and `AGENTS.md` from the actor's real repository at `C:\Users\Stef\apify-portfolio\diario-oficial-cl-monitor`. No `CHANGELOG.md` exists in this repo; V2 architecture detail came from `AGENTS.md`'s "Delta engine v2 (2026-09-08)" section instead.*

# Actor input Schema

## `sections` (type: `array`):

Which sections of the edition to fetch. Not every section publishes content every day - a section with nothing that day returns 404 from the source and is skipped, not treated as an error.

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

Hard cap on the number of publications returned this run, across all selected sections.

## `onlyNew` (type: `boolean`):

Return only publications that are new or amended (a correction re-published under the same CVE) since a prior run today, tracked in a named key-value store scoped to this actor. Most useful re-running the same day's edition on a schedule to catch late additions/corrections. There is no CLOSED or status-change event in this domain - a published legal notice is never withdrawn or 'closed', it is a permanent public record.

## `eventTypes` (type: `array`):

Which kinds of change to deliver when 'Only new records' is on (ignored, everything delivered, when it is off). NEW\_LISTING = never seen before. UPDATED = same CVE (or identity), the content changed - a correction.

## Actor input object example

```json
{
  "sections": [
    "normas_generales"
  ],
  "maxItems": 300,
  "onlyNew": false,
  "eventTypes": [
    "NEW_LISTING",
    "UPDATED"
  ]
}
```

# Actor output Schema

## `results` (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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("stefano_seggio/diario-oficial-cl-monitor").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("stefano_seggio/diario-oficial-cl-monitor").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 '{}' |
apify call stefano_seggio/diario-oficial-cl-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,stefano_seggio/diario-oficial-cl-monitor"
        }
    }
}

```

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/qfBeEKuLfYUw9UOuW/builds/QViVleXlX5PzXdYhb/openapi.json
