# Structured Data Extractor (`zinin/structured-extract`) Actor

Extract title, meta, JSON-LD, headings, links, emails, and price observations from up to 100 authorized public static HTML pages. Delivered rows include source identity, selected fields, confidence, gaps, next action, retry status, and billing. No browser or LLM inference; non-delivery is free.

- **URL**: https://apify.com/zinin/structured-extract.md
- **Developed by:** [Tim Zinin](https://apify.com/zinin) (community)
- **Categories:** Developer tools, Automation
- **Features:** Limited permissions
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $1.70 / 1,000 delivered structured pages

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

## Structured Extract — Typed Public Page Evidence for Automations

> Turn selected public pages into bounded JSON fields with provenance, confidence, missing-data truth, and explicit action routing.

This Store guide treats the Actor as a commercial data product: the raw observation, its source identity, evidence quality, gaps, recommended next step, delivery state, and billing meaning travel together. It helps a buyer answer a bounded question; it never converts public data into permission or certainty.

![Structured Page Evidence: buyer input to evidence-backed action](https://raw.githubusercontent.com/TimmyZinin/apify-actor-assets/f8524e8a9205a4f277d6dd79826bc76275962f35/commercial115/structured-extract/readme-hero.webp)

### The decision this product supports

**Which requested page fields were actually observed, and where does a human or downstream system need to verify gaps?**

The Actor reduces repetitive collection and first-pass triage. A result is useful because it is structured and reviewable, not because it eliminates human judgment.

### Who uses it

| Buyer or operator | What they get |
| --- | --- |
| Marketing operations | Extract page titles, descriptions, headings, links, public emails, prices, and structured metadata into staging tables. |
| Small agencies | Build source-linked client audits and enrichment workflows from approved page lists. |
| AI and automation builders | Give agents typed page facts instead of raw HTML while keeping evidence boundaries visible. |
| Ecommerce researchers | Observe public price strings and JSON-LD without claiming inventory, revenue, or transaction facts. |
| Data teams | Use selectable field groups and stable row semantics for bounded ingestion jobs. |

### Input contract

| Input field | How to use it |
| --- | --- |
| urls | Required list of up to 100 public HTTP(S) URLs, normalized and deduplicated. |
| fields | Optional subset of title, description, image, siteName, canonical, jsonLd, headings, links, emails, and prices. Empty means all supported groups. |
| maxConcurrency | Parallel page processing from 1 to 30. Use a small value for first-run validation. |

#### Recommended first Input

```json
{
  "urls": [
    "https://example.com"
  ],
  "fields": [
    "title",
    "description",
    "headings",
    "links"
  ],
  "maxConcurrency": 2
}
```

Run the bounded example first. Inspect all returned row types and KVS `OUTPUT` before increasing volume or concurrency.

### Output examples: success, partial, and failure

These are compact contract examples derived from the Actor's acceptance fixtures and decision-layer tests. Dates, counts, titles, and registry or filing identifiers are representative, not current market, medical, or filing claims. A production consumer must use the values returned by its own run and retain the complete row.

#### Successful observation shape

```json
{
  "url": "https://example.com/",
  "found": true,
  "title": "Example Domain",
  "description": null,
  "headings": [
    "Example Domain"
  ],
  "links": [
    "https://www.iana.org/domains/example"
  ],
  "partial": false,
  "confidenceScore": 70,
  "confidenceBand": "medium",
  "recommendedAction": "USE_EXTRACTED_FIELDS_WITH_PROVENANCE",
  "safeToAutomate": false,
  "failureType": null,
  "retryable": false
}
```

Interpret this row under the rule: A successful row means one or more requested structured field groups were observed in a bounded public response. It does not verify identity, consent, commercial intent, availability, or source truth.

#### Partial or budget-stopped shape

```json
{
  "recordType": "advisory",
  "partial": true,
  "confidenceBand": "low",
  "recommendedAction": "REVIEW_PARTIAL_RESULT",
  "safeToAutomate": false,
  "dataGaps": [
    "The configured or source boundary prevented a complete observation."
  ],
  "failureType": "budget_exhausted",
  "retryable": true,
  "billing": {
    "billable": false,
    "eventName": null
  }
}
```

The partial row is not a negative business fact. Preserve the gap, do not bill the advisory, and resume only the unfinished authorized scope.

#### Source-failure shape

```json
{
  "recordType": "advisory",
  "found": false,
  "error": "source unavailable",
  "confidenceScore": 0,
  "confidenceBand": "none",
  "recommendedAction": "REVIEW_SOURCE_FAILURE",
  "safeToAutomate": false,
  "failureType": "source_unavailable",
  "retryable": true,
  "billing": {
    "billable": false,
    "eventName": null
  }
}
```

The failure row must never enter a positive-results lane. Retry only when `retryable=true`; otherwise correct the input or policy issue first.

![Structured Page Evidence: evidence-to-action workflow](https://raw.githubusercontent.com/TimmyZinin/apify-actor-assets/f8524e8a9205a4f277d6dd79826bc76275962f35/commercial115/structured-extract/readme-workflow.webp)

### Field dictionary

| Field or group | Meaning |
| --- | --- |
| url, finalUrl, entityId, observedAt | Input/final source identity, stable key, and observation time. |
| title, description, image, siteName, canonical | Observed document and social metadata, with null retained when absent. |
| jsonLd, headings, links, emails, prices | Bounded arrays parsed from the public response. |
| found, partial, error | Usability, completeness, and source failure truth. |
| confidenceScore, confidenceBand, confidenceReasons, confidenceRisks | Support for the factual extraction, not business value. |
| sourceEvidence, dataGaps, negativeSignals | Provenance and facts the response cannot establish. |
| recommendedAction, actionPriority, actionReason, safeToAutomate | Review routing with automation disabled by default. |
| failureType, retryable, failureDiagnostics, billing | Operational handling and per-row delivery/billing semantics. |

#### Common decision fields

| Field | Operational meaning |
| --- | --- |
| recordType | The semantic row family. Use it to distinguish a business result from an advisory or terminal record. |
| schemaVersion | Version of the additive decision-intelligence contract. Pin or validate it in strict consumers. |
| entityId | Stable entity identity for deduplication and joins. It is not necessarily a legal identifier. |
| inputRef | The relevant submitted input reference after normalization. |
| observedAt | When the Actor observed or finalized the evidence. It is not necessarily the source publication time. |
| firstSeenAt and lastSeenAt | Always-emitted observation boundaries. Stateful monitors use the compatible baseline/current boundary. Stateless rows set both equal to observedAt for the current run; that equality does not establish historical tenure. |
| freshness | A structured statement about evidence age or availability, not a prediction. Its basis and age unit follow the source-specific field definition. |
| eventId | For monitors, the stable identity of one observed transition or monitor outcome. It is distinct from entityId. |
| before and after | For monitors, the bounded comparable snapshots used for the decision. Null means that side of a comparison was not honestly available. |
| changedFields and changeFlags | Machine-readable monitor deltas and normalized change labels. Empty arrays mean no supported changed field was established, not that every possible real-world fact stayed constant. |
| materialityScore and materialityBand | Magnitude of an observed monitor change when the Actor can calculate it. Materiality is separate from evidence confidence and may be unknown when the source lacks the required facts. |
| confidenceScore | Evidence support on a 0–100 scale. It is separate from materiality, lead score, or business value. |
| confidenceBand | Readable high/medium/low/unknown grouping of evidence support. |
| confidenceReasons | Observed facts that raise confidence. |
| confidenceRisks | Missing, partial, ambiguous, inferred, or conflicting aspects that reduce confidence. |
| confidenceConflict | Explicit consistency warning when structured evidence does not reconcile. |
| sourceEvidence | Source-linked observations supporting the row. Preserve this during export. |
| dataGaps | Important evidence the Actor did not observe or cannot establish. Keep these gaps visible in CRM, spreadsheet, and automation exports. |
| negativeSignals | Machine-readable risks or gaps. A negative signal is not automatically a negative business outcome. |
| recommendedAction | Bounded review label produced from the available evidence. |
| actionPriority | Suggested queue priority, not urgency guaranteed by the source. |
| actionReason | Plain-language explanation for the recommended action. |
| safeToAutomate | Whether the narrow recommended action is deterministic enough for automation. Organizational policy still applies. |
| failureType | Normalized terminal or partial failure classification. Null means no classified failure. |
| retryable | Whether a later retry may legitimately change an operationally incomplete result. |
| recommendation | Human-readable handling guidance, especially for terminal rows. |

### Evidence, confidence, and honest boundaries

#### What the evidence supports

- Fields are parsed deterministically from a bounded public HTTP response.
- Only requested field groups are returned; missing observations remain empty or null.
- Links and evidence retain the page context needed for human verification.
- Public email strings are observations, not mailbox, identity, consent, or deliverability verification.
- Run OUTPUT reconciles complete, partial, failed, free, paid, and withheld delivery state.

#### What this Actor never claims

- It does not render client-side JavaScript or bypass authentication, robots policy, or private network boundaries.
- It does not verify a public email mailbox, person identity, consent, or permission to contact.
- It does not interpret a price string as current stock, final transaction price, tax treatment, or availability.
- It does not guarantee that page metadata is truthful or current after observation.
- It does not authorize automatic CRM mutation, outreach, purchase, or publication.

#### Reading data gaps correctly

A data gap is part of the result. Nulls, partial flags, confidence risks, source failures, and unavailable fields must survive export. Removing these fields makes the remaining facts look more complete than they are. When two sources conflict or a required identity cannot be proven, lower confidence and keep `safeToAutomate=false`.

#### Source evidence is not permission

A public source proves only that a value or statement was observable at the recorded time and URL. It does not establish consent, contractual rights, legal status, accuracy after observation, or authorization for a downstream action. Your organization remains responsible for source terms, privacy rules, outreach policy, retention, and human review.

### Decision policy and action routing

| Action | How to use it |
| --- | --- |
| USE_EXTRACTED_FIELDS_WITH_PROVENANCE | Stage the observed fields with source evidence and verify material facts before external use. |
| CHECK_PAGE_RENDERING_OR_FIELD_SCOPE | Inspect whether the requested facts are absent, dynamic, or outside the selected field set. |
| REVIEW_PARTIAL_EXTRACTION | Treat delivered fields as incomplete and investigate the limiting boundary. |
| REVIEW_SOURCE_FAILURE | Use failureType and retryable to decide whether correction or a later retry is appropriate. |

#### Confidence is not attractiveness

`confidenceScore` answers “how strongly does the available evidence support this factual classification?” It does not answer “how valuable is this lead, property, account, or address?” A high-confidence negative fact may be commercially uninteresting; a low-confidence positive signal may deserve research but not action. Keep the concepts separate in dashboards, exports, and CRM fields.

#### Why safeToAutomate is conservative

`safeToAutomate` is intentionally false whenever the next step could amplify an uncertain inference. It may be true only for narrow deterministic actions explicitly supported by the row, such as suppressing an email with invalid syntax. A true value does not waive legal, privacy, consent, contractual, or organizational rules.

#### Retry policy

- Retry when `retryable=true` and the failure is operational, such as a temporary source or DNS problem.
- Do not endlessly retry deterministic invalid input, policy refusal, or confirmed absence.
- A retry must preserve the original input reference and must not create duplicate downstream actions.
- Budget exhaustion is not negative evidence about the entity. Resume only the unprocessed scope with an authorized budget.
- A failed Actor run is an operational event. Never transform it into “no listing,” “no contact,” “bad lead,” or “invalid email.”

### Commercial use-case playbooks

#### 1. CRM staging enrichment

**Goal.** Extract approved company pages into staging fields and require review before promotion into canonical CRM records.

**Recommended runbook.**

1. Define the submitted cohort and write down why it is in scope.
2. Start with the smallest useful Input and preserve the exact run ID.
3. Inspect the Dataset overview before exporting anything.
4. Check `failureType`, `retryable`, completeness indicators, and `confidenceBand`.
5. Open the relevant `sourceEvidence` or source URL for material rows.
6. Apply the recommended action as a review label, not as an instruction to contact, buy, delete, accuse, or publish.
7. Record the analyst's final disposition in the destination system.

**Do not skip.** A successful row means one or more requested structured field groups were observed in a bounded public response. It does not verify identity, consent, commercial intent, availability, or source truth.

#### 2. Content audit

**Goal.** Collect titles, descriptions, headings, and canonical links, then route missing or conflicting fields to an editor.

**Recommended runbook.**

1. Define the submitted cohort and write down why it is in scope.
2. Start with the smallest useful Input and preserve the exact run ID.
3. Inspect the Dataset overview before exporting anything.
4. Check `failureType`, `retryable`, completeness indicators, and `confidenceBand`.
5. Open the relevant `sourceEvidence` or source URL for material rows.
6. Apply the recommended action as a review label, not as an instruction to contact, buy, delete, accuse, or publish.
7. Record the analyst's final disposition in the destination system.

**Do not skip.** A successful row means one or more requested structured field groups were observed in a bounded public response. It does not verify identity, consent, commercial intent, availability, or source truth.

#### 3. Public contact research

**Goal.** Observe email strings with source pages, then verify mailbox, identity, consent, and suppression policy elsewhere.

**Recommended runbook.**

1. Define the submitted cohort and write down why it is in scope.
2. Start with the smallest useful Input and preserve the exact run ID.
3. Inspect the Dataset overview before exporting anything.
4. Check `failureType`, `retryable`, completeness indicators, and `confidenceBand`.
5. Open the relevant `sourceEvidence` or source URL for material rows.
6. Apply the recommended action as a review label, not as an instruction to contact, buy, delete, accuse, or publish.
7. Record the analyst's final disposition in the destination system.

**Do not skip.** A successful row means one or more requested structured field groups were observed in a bounded public response. It does not verify identity, consent, commercial intent, availability, or source truth.

#### 4. Ecommerce page normalization

**Goal.** Extract public JSON-LD and price strings for comparison while retaining nulls and interpretation boundaries.

**Recommended runbook.**

1. Define the submitted cohort and write down why it is in scope.
2. Start with the smallest useful Input and preserve the exact run ID.
3. Inspect the Dataset overview before exporting anything.
4. Check `failureType`, `retryable`, completeness indicators, and `confidenceBand`.
5. Open the relevant `sourceEvidence` or source URL for material rows.
6. Apply the recommended action as a review label, not as an instruction to contact, buy, delete, accuse, or publish.
7. Record the analyst's final disposition in the destination system.

**Do not skip.** A successful row means one or more requested structured field groups were observed in a bounded public response. It does not verify identity, consent, commercial intent, availability, or source truth.

#### 5. Agent tool endpoint

**Goal.** Let an agent request only needed fields and require it to cite sourceEvidence rather than invent missing facts.

**Recommended runbook.**

1. Define the submitted cohort and write down why it is in scope.
2. Start with the smallest useful Input and preserve the exact run ID.
3. Inspect the Dataset overview before exporting anything.
4. Check `failureType`, `retryable`, completeness indicators, and `confidenceBand`.
5. Open the relevant `sourceEvidence` or source URL for material rows.
6. Apply the recommended action as a review label, not as an instruction to contact, buy, delete, accuse, or publish.
7. Record the analyst's final disposition in the destination system.

**Do not skip.** A successful row means one or more requested structured field groups were observed in a bounded public response. It does not verify identity, consent, commercial intent, availability, or source truth.

### Integration recipes

All examples use placeholders. Keep the Apify token in a secret manager and never write it into a Dataset, README, screenshot, or client-side application.

#### cURL: start a run and wait briefly

```bash
curl -sS -X POST 'https://api.apify.com/v2/acts/zinin~structured-extract/runs?waitForFinish=60' \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H 'Content-Type: application/json' \
  --data '{"urls":["https://example.com"],"fields":["title","description","headings","links"],"maxConcurrency":2}'
```

The run response includes `defaultDatasetId`. Read clean JSON rows with:

```bash
curl -sS "https://api.apify.com/v2/datasets/$DEFAULT_DATASET_ID/items?clean=true&format=json" \
  -H "Authorization: Bearer $APIFY_TOKEN"
```

#### JavaScript with apify-client

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const input = {
  "urls": [
    "https://example.com"
  ],
  "fields": [
    "title",
    "description",
    "headings",
    "links"
  ],
  "maxConcurrency": 2
};
const run = await client.actor('zinin/structured-extract').call(input);
const { items } = await client.dataset(run.defaultDatasetId).listItems({ clean: true });

for (const row of items) {
    console.log({
        entityId: row.entityId,
        confidenceBand: row.confidenceBand,
        recommendedAction: row.recommendedAction,
        safeToAutomate: row.safeToAutomate,
        failureType: row.failureType,
    });
}
```

#### Python with apify-client

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("zinin/structured-extract").call(run_input={
    "urls": [
        "https://example.com"
    ],
    "fields": [
        "title",
        "description",
        "headings",
        "links"
    ],
    "maxConcurrency": 2
})

for row in client.dataset(run["defaultDatasetId"]).iterate_items(clean=True):
    print({
        "entityId": row.get("entityId"),
        "confidenceBand": row.get("confidenceBand"),
        "recommendedAction": row.get("recommendedAction"),
        "safeToAutomate": row.get("safeToAutomate"),
        "failureType": row.get("failureType"),
    })
```

#### Apify MCP call

```json
{
  "name": "call-actor",
  "arguments": {
    "actor": "zinin/structured-extract",
    "input": {
      "urls": [
        "https://example.com"
      ],
      "fields": [
        "title",
        "description",
        "headings",
        "links"
      ],
      "maxConcurrency": 2
    }
  }
}
```

#### Generic webhook consumer policy

1. Trigger on a terminal Actor run event.
2. Confirm the run status is `SUCCEEDED` before reading business rows.
3. Retrieve rows from `defaultDatasetId`.
4. Reject or quarantine rows whose `failureType` is non-null unless your policy explicitly handles that failure.
5. Send `safeToAutomate=false` rows to a human-review queue.
6. Store `entityId`, `observedAt`, `sourceEvidence`, confidence, action, and the Apify run ID together.
7. Make retries idempotent by keying the destination on the stable entity ID plus the intended observation or event identity.

### Where this fits in a practical stack

| Destination | Recommended pattern |
| --- | --- |
| Apify Console | Use the visual Input form, start the run, then open the default Dataset overview. This is the fastest path for a one-off review and the best place to inspect evidence before automating anything. |
| Apify API | POST JSON input to the Actor run endpoint, wait or poll for completion, then read the default Dataset through the URL returned by the run object. |
| JavaScript client | Use apify-client from a Node.js service, pass the same JSON object as the Console Input, and preserve the returned run and Dataset IDs in your own audit log. |
| Python client | Use apify-client in a Python enrichment job, iterate Dataset items, and route rows by recommendedAction, confidenceBand, failureType, and retryable. |
| Make | Start the Actor from a scenario, wait for the run, retrieve Dataset items, filter unsafe or low-confidence rows, then insert review-ready rows into the destination application. |
| Zapier | Use an Apify run action or webhook trigger, fetch Dataset items, apply a Filter step, and send only review-approved fields into the next sales or operations step. |
| n8n | Use HTTP Request or Apify nodes, branch on failureType and retryable, keep a manual-review lane for safeToAutomate=false, and write sourceEvidence together with the business fields. |
| Google Sheets | Export the Dataset directly or append rows from an automation. Keep stable entityId as a hidden key so reruns update the correct record instead of creating ambiguous duplicates. |
| Airtable | Map entityId to a primary or deduplication field, store confidence and evidence in separate columns, and expose recommendedAction as the triage view. |
| Webhook | Configure an Apify webhook for terminal run states, retrieve the Dataset after SUCCEEDED, and treat FAILED or TIMED-OUT runs as operational events rather than negative business evidence. |

#### A safe automation shape

The Actor is a collection and decision-support component. A production workflow should keep raw evidence, decision metadata, and business action in distinct layers:

1. **Collect:** run the Actor with explicit bounded input.
2. **Validate:** require a successful run and schema-valid Dataset rows.
3. **Triage:** branch on `failureType`, `retryable`, `confidenceBand`, and `safeToAutomate`.
4. **Review:** open source evidence for rows that may affect a person, campaign, investment, compliance decision, or customer record.
5. **Act:** execute only the action approved by your own policy and authorized operator.
6. **Audit:** retain run ID, Dataset ID, observation time, input reference, source evidence, and the final human decision.

This separation prevents a common automation error: turning “data was observed” into “a business action is justified.”

### Operating guide

#### Before the first production run

1. Write the business question in one sentence: **Which requested page fields were actually observed, and where does a human or downstream system need to verify gaps?**
2. Confirm every submitted input is within your authorized scope.
3. Use the prefilled small example and review all returned row types.
4. Map stable identifiers, confidence, evidence, actions, gaps, failure, and retry fields into the destination.
5. Establish a human owner for review exceptions.
6. Set a run budget and output bound appropriate to the test.
7. Verify that secrets are stored only in the platform or workflow secret manager.

#### After every scheduled run

1. Check terminal run status and logs.
2. Compare the number of submitted entities, produced business rows, and advisory rows.
3. Review partial, unknown, conflict, and low-confidence buckets.
4. Inspect a sample of source evidence, including at least one positive and one negative result.
5. Confirm the destination deduplicated on the intended stable key.
6. Verify that no downstream action was triggered from an error row.
7. Track cost per useful reviewed row rather than cost per raw request alone.

#### Production monitoring signals

Monitor source-unavailable rate, partial-row rate, low-confidence share, missing evidence, retry volume, run duration, Dataset row count, and spend. A sudden shift may indicate source drift, input drift, or an upstream outage. Stop automation and investigate before accepting a new pattern as business truth.

#### Cost control

Begin with one or two representative URLs and only the fields your workflow needs. Validate array bounds, null handling, evidence, and current live event pricing before scaling.

Use `maxTotalChargeUsd` when calling a monetized Actor if your workflow supports it. Treat a buyer-set cap as a hard safety boundary. If the cap stops work, the unfinished items remain unprocessed; they do not become negative results.

### Pricing and billing contract

Current prices are shown by Apify on the live Store page and are authoritative. The Actor links a billable `result-found` event to a successfully delivered useful row. Advisory, no-match, source-failure, and budget-stop rows use the free channel only when the runtime confirms default Dataset writes are unpriced. If pricing cannot be read safely, the Actor fails closed. Concurrent workers serialize the budget check and linked delivery so they cannot independently pass the same remaining-budget test.

Use a small representative run to calculate cost per useful reviewed row. A buyer-set maximum charge is a hard boundary; unprocessed rows remain unprocessed rather than becoming negative evidence.

### Production acceptance checklist

- \[ ] The business question matches: **Which requested page fields were actually observed, and where does a human or downstream system need to verify gaps?**
- \[ ] Inputs are authorized, bounded, deduplicated, and tested on a small representative sample.
- \[ ] The destination stores `entityId`, `observedAt`, source evidence, confidence, gaps, action, and failure fields.
- \[ ] Dataset result rows and KVS `OUTPUT` reconcile with the submitted scope.
- \[ ] Partial, failure, free-advisory, and budget-stopped rows cannot enter the positive-results lane.
- \[ ] `safeToAutomate=false` creates a visible human-review task.
- \[ ] Retries are idempotent and cannot duplicate downstream actions or charges.
- \[ ] The live pricing panel and a small canary run were reviewed before scale-up.
- \[ ] Source terms, privacy, retention, consent, and organizational policy were reviewed for the intended use.
- \[ ] A named operator owns source drift, low-confidence exceptions, and rollback.

### Frequently asked questions

#### Is this a database?

No. It is an on-demand observation tool. Each run collects or evaluates the submitted scope and records evidence at that time.

#### Does a found row prove commercial interest?

No. A found row proves only the factual observation described by its fields. Buyer intent is never inferred.

#### Can I automatically contact every result?

No. Use recommendedAction as triage, verify the evidence and identity, and apply your own consent, privacy, suppression, and outreach rules.

#### Why is safeToAutomate often false?

Because a useful observation can still require identity, context, legal, or source verification before action. Conservative routing prevents false certainty from scaling.

#### What should I do with low confidence?

Open confidenceRisks and sourceEvidence, close the important gap, or keep the row in a manual queue. Do not hide the confidence field.

#### What does partial mean?

The Actor obtained some usable evidence but could not support a complete observation of the configured scope. Partial is not the same as empty.

#### What is a confirmed zero?

Only an explicit source or deterministic rule can support a confirmed absence. An outage, truncation, or unreadable response is not a zero.

#### Should I retry every failure?

No. Retry only when retryable is true. Invalid input, policy refusal, or deterministic classification should be corrected or handled, not looped.

#### Can I delete failure rows?

You can exclude them from a business-results view, but retain them in operational logs so Dataset completeness and retry decisions stay explainable.

#### How should I deduplicate?

Use entityId for the entity and, for stateful monitors, eventId for the observed transition. Also retain the Apify run ID.

#### Can I treat confidence as conversion probability?

No. Confidence measures evidence support, not purchase probability, revenue, suitability, or expected return.

#### Can I change the recommended action?

Yes. It is an explainable default. Your downstream policy can be stricter, and should encode organization-specific authorization and risk tolerance.

#### How do I estimate cost?

Run the smallest representative input, inspect live event prices and run usage in Apify, then model the number of billable result events. The live pricing panel is authoritative.

#### Why use a small prefill?

It produces a cheap, fast, inspectable first run and reduces the chance of scaling a wrong input or workflow assumption.

#### Can I schedule it?

Yes. Use an Apify schedule, but make the destination idempotent and review changes in failure, partial, and confidence rates.

#### Can I export CSV or Excel?

Yes. Apify Datasets support common export formats. JSON is recommended when you need nested evidence and decision fields.

#### Can I send results to Sheets or Airtable?

Yes. Preserve entityId, confidence, evidence, gaps, actions, and failure fields instead of mapping only the headline value.

#### Can I use it from Make, Zapier, or n8n?

Yes. Start the Actor, wait for a successful terminal state, read Dataset items, then branch on decision and failure fields.

#### Can an LLM consume the output?

Yes, but pass the structured evidence and limitations together. Instruct the model not to invent missing facts and to cite sourceEvidence.

#### What happens when a source changes?

The run may become partial, unavailable, or fail validation. Monitor these rates and inspect logs before treating changed output as a real-world shift.

#### Does public mean unrestricted?

No. Public visibility does not remove source terms, privacy obligations, retention rules, or the need for a legitimate downstream purpose.

#### Is a source URL permanent?

Not necessarily. Store observation time and material facts because web content can change or disappear.

#### Can I rely on one row for a high-stakes decision?

No. High-stakes legal, financial, employment, compliance, safety, or personal decisions require appropriate primary evidence and qualified review.

#### How do I report a suspected parsing issue?

Provide the Actor run ID, a redacted input, affected field, expected source evidence, and whether the issue reproduces. Never include tokens or private data.

#### What does success mean?

A successful row means one or more requested structured field groups were observed in a bounded public response. It does not verify identity, consent, commercial intent, availability, or source truth.

### Support information

Provide the public Actor name, run ID, Dataset item index or `entityId`, a redacted Input, affected source URL, expected behavior, observed behavior, and whether a bounded retry reproduced it. Never include Apify tokens, private customer records, credentials, or unnecessary personal data.

### Final interpretation rule

A successful row means one or more requested structured field groups were observed in a bounded public response. It does not verify identity, consent, commercial intent, availability, or source truth.

# Actor input Schema

## `urls` (type: `array`):

Authorized public HTTP(S) page URLs. Normalized duplicates are processed once; unsafe or failed targets return free advisory rows.

## `fields` (type: `array`):

Optional subset of fields to return: title, description, image, siteName, canonical, jsonLd, headings, links, emails, prices. Leave empty to extract all of them.

## `maxConcurrency` (type: `integer`):

How many URLs to process in parallel.

## Actor input object example

```json
{
  "urls": [
    "https://example.com",
    "https://www.iana.org/help/example-domains"
  ],
  "fields": [],
  "maxConcurrency": 10
}
```

# Actor output Schema

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

API URL for the default dataset items produced by this run.

## `OUTPUT` (type: `string`):

Counts requested, unique, attempted, delivered, paid, free, failed, and withheld rows, plus partial and replay-safety state.

# 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 = {
    "urls": [
        "https://example.com",
        "https://www.iana.org/help/example-domains"
    ],
    "fields": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("zinin/structured-extract").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 = {
    "urls": [
        "https://example.com",
        "https://www.iana.org/help/example-domains",
    ],
    "fields": [],
}

# Run the Actor and wait for it to finish
run = client.actor("zinin/structured-extract").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 '{
  "urls": [
    "https://example.com",
    "https://www.iana.org/help/example-domains"
  ],
  "fields": []
}' |
apify call zinin/structured-extract --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,zinin/structured-extract"
        }
    }
}
```

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/Arqpxuec92WnoF5Ha/builds/eQg99Sa8C4xcKcUEy/openapi.json
