# Search Evidence Validator (`skilled_glee/search-evidence-validator`) Actor

Validate public search-result URLs for relevance, freshness, content depth, citation readiness, reachability, and deterministic evidence quality before downstream agent use.

- **URL**: https://apify.com/skilled\_glee/search-evidence-validator.md
- **Developed by:** [Dakota Myers](https://apify.com/skilled_glee) (community)
- **Categories:** AI, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $10.00 / 1,000 validated pages

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

## Search Evidence Validator

Validate search-result pages before an agent trusts, cites, summarizes, or spends more money on them.

Search Evidence Validator is a machine-consumable Apify Actor that fetches public HTTP(S) pages and returns explicit evidence-quality records. It measures reachability, query relevance, content depth, freshness, and citation readiness; extracts citation metadata and an evidence excerpt; fingerprints the fetched text with SHA-256; and assigns each page `ACCEPT`, `REVIEW`, or `REJECT`.

### When an agent should call it

Use this Actor after search or discovery and before expensive downstream work.

A typical machine workflow is:

```text
search/discovery
      ↓
candidate URLs
      ↓
Search Evidence Validator
      ↓
ACCEPT / REVIEW / REJECT + evidence record
      ↓
cite, summarize, buy another tool call, or discard
```

It is useful when an agent needs to answer questions such as:

- Is this search result actually reachable right now?
- Does the page contain the terms the upstream query was looking for?
- Is the page substantial enough to use as evidence?
- Does it expose a usable title, canonical URL, publication time, and HTTPS source?
- Has the page content changed since a previous run?
- Should downstream work accept, manually review, or reject this source?

It does **not** replace semantic fact-checking, source-authority judgment, or claim-level verification. It is a deterministic pre-filter and evidence-normalization layer for public web pages.

### Input

Provide either `urls` or richer `results` objects. Add `query` when you want query-term relevance scoring.

Up to 20 candidate pages can be processed in one run.

#### Minimal input

```json
{
  "query": "example domains",
  "urls": [
    "https://www.iana.org/help/example-domains"
  ],
  "maxResults": 1,
  "timeoutMs": 8000
}
```

#### Search-provider input

```json
{
  "query": "example domains",
  "results": [
    {
      "url": "https://www.iana.org/help/example-domains",
      "title": "Example Domains",
      "publishedAt": "2017-05-13"
    }
  ],
  "maxResults": 10
}
```

Supported fields:

| Field | Type | Purpose |
| --- | --- | --- |
| `query` | string | Optional upstream query used for relevance scoring. |
| `urls` | string\[] | Public HTTP(S) URLs. |
| `results` | object\[] | Search results containing `url` and optional `title` / `publishedAt`. |
| `maxResults` | integer | 1–20 candidates, default 10. |
| `timeoutMs` | integer | Per-page fetch timeout, 1,000–12,000 ms, default 8,000. |

Provide at least one URL through `urls` or `results`.

### Output contract

The default dataset contains one record per processed candidate.

Example from the live acceptance fixture:

```json
{
  "url": "https://www.iana.org/help/example-domains",
  "finalUrl": "https://www.iana.org/help/example-domains",
  "status": 200,
  "title": "Example Domains",
  "canonical": "https://www.iana.org/help/example-domains",
  "wordCount": 158,
  "query": "example domains",
  "matchedQueryTerms": ["example", "domains"],
  "relevanceScore": 1,
  "freshnessScore": 0,
  "depthScore": 0.1756,
  "citationScore": 1,
  "qualityScore": 0.7351,
  "decision": "REVIEW",
  "issues": [],
  "contentSha256": "9ef0c234acc6d8cbf49013291834d2a263696bee76feeef6b5a40f0d526e0d16"
}
```

Records can also include `description`, `publishedAt`, `ageDays`, an evidence `excerpt`, and `accessedAt`.

A failed fetch produces a `REJECT` record with `qualityScore: 0` and an explicit issue instead of silently disappearing.

### Decision contract

The overall score is intentionally inspectable rather than opaque.

```text
30% query relevance
25% reachability / HTTP health
20% content depth
15% citation readiness
10% freshness
```

Decision thresholds:

| Score | Decision |
| --- | --- |
| `>= 0.75` | `ACCEPT` |
| `>= 0.50` and `< 0.75` | `REVIEW` |
| `< 0.50` | `REJECT` |

Issues can include signals such as non-2xx status, missing title, thin content, low query relevance, or non-HTTPS transport.

The scoring contract is explicit and repeatable. Freshness naturally changes as a publication ages. `contentSha256` is the stable fingerprint for unchanged extracted page text.

### Pricing

This Actor is live on Apify with **pay per event** pricing.

- `validated-page`: **$0.01** per successfully fetched and scored page
- `apify-actor-start`: **$0.00005** once per run
- minimum configured successful-run charge: **$0.01005**

The `validated-page` event is charged only after a successful page result has been produced and pushed. Fetch failures still return diagnostic `REJECT` rows but do not become `validated-page` charges.

The Actor is public, uses `LIMITED_PERMISSIONS`, has Standby disabled, and is currently discoverable through Apify's agentic Store filtering for PPE Actors.

Apify's x402 execution boundary can require a platform-level prepaid/payment amount that is separate from this Actor's per-event price. An unauthenticated x402 preflight currently exposes a Base-mainnet USDC payment challenge before execution; the Actor's own billing remains the PPE event schedule above.

### Machine-facing behavior

The Actor is designed to sit behind search APIs, research agents, RAG ingestion, citation pipelines, procurement agents, and other systems that need a cheap quality gate before committing more tokens or money.

Useful downstream patterns include:

```text
if decision == ACCEPT:
    continue automatically
elif decision == REVIEW:
    require stronger corroboration or a second source
else:
    discard candidate
```

The SHA-256 fingerprint can also be persisted by a caller to detect whether extracted page text changed between validation runs.

### Safety boundaries

Network fetching is intentionally constrained so the Actor cannot be used as a general internal-network probe.

It:

- accepts only HTTP and HTTPS;
- rejects loopback, private, link-local, reserved, carrier-grade NAT, multicast, documentation, and common internal targets;
- blocks internal-style DNS suffixes such as `.localhost`, `.local`, `.internal`, `.home`, and `.lan`;
- resolves DNS before connecting and rejects a hostname if any returned address is private;
- pins the request to a validated resolved address;
- revalidates every redirect;
- follows at most three redirects;
- rejects URLs containing credentials;
- forwards no caller-supplied credentials or arbitrary headers;
- limits URLs to 2,048 characters;
- caps fetched response data at 750 KB;
- caps per-page timeout at 12 seconds.

### Limits

This Actor validates public HTML-style evidence. It is not a browser renderer, login/session client, CAPTCHA bypasser, private-network scanner, authority-ranking engine, or claim-level truth oracle.

JavaScript-only pages may expose limited text when the initial HTTP response does not contain the rendered content. Use a browser-capable extraction step upstream when rendering is required, then pass the resulting public evidence source through the appropriate verification pipeline.

### Live proof

The deployment pipeline requires all of the following before `latest` is considered healthy:

1. deterministic tests pass;
2. Apify cloud build succeeds;
3. `latest` is applied;
4. a real Apify cloud run executes against a public fixture;
5. the returned dataset item matches the output contract.

The current production line has passed that gate and is publicly Store-indexed, PPE-monetized, agentic-discoverable, and x402-challenge reachable. A non-owner paid run has **not** yet been claimed as proof of demand.

# Actor input Schema

## `query` (type: `string`):

Optional query used to score result relevance.

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

Public HTTP(S) URLs to fetch and validate.

## `results` (type: `array`):

Optional search result objects with URL, title, and publication time metadata.

## `maxResults` (type: `integer`):

Maximum number of candidate pages to validate in one run.

## `timeoutMs` (type: `integer`):

Maximum fetch time allowed for each page.

## Actor input object example

```json
{
  "maxResults": 10,
  "timeoutMs": 8000
}
```

# 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("skilled_glee/search-evidence-validator").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("skilled_glee/search-evidence-validator").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 skilled_glee/search-evidence-validator --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,skilled_glee/search-evidence-validator"
        }
    }
}
```

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/IBts7w3x79cGmp91m/builds/G1lXpl1TxmrVwfeBy/openapi.json
