# MarketCheck — Regional SEO Audit (`dushan219/marketcheck-regional-seo-audit`) Actor

Audit regional storefront HTTP responses, redirect chains, canonical tags and hreflang links. Verify linked targets and return annotations, then export JSON, CSV and HTML evidence reports. Raw HTTP checks with bounded requests; no paid proxies required.

- **URL**: https://apify.com/dushan219/marketcheck-regional-seo-audit.md
- **Developed by:** [dushan](https://apify.com/dushan219) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

## 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

## MarketCheck — Regional SEO Audit

Inspect the actual HTTP response and regional SEO annotations of public storefront URLs. MarketCheck follows redirects, extracts canonical and hreflang tags, and checks linked targets and hreflang return links. Export evidence as JSON, CSV and HTML.

### Input

Supply 1–20 exact URLs in startUrls. maxRequests defaults to 60 and accepts 1–200; every HTTP request and redirect counts. verifyTargets defaults to true. URLs explicitly supplied in the input are prioritized during target checking. Example:

```json
{"startUrls":[{"url":"https://www.glossier.com/en-ca"},{"url":"https://www.glossier.com/en-lk"}],"maxRequests":60,"verifyTargets":true}
```

For SKIMS use examples/skims-regional.json, discovered from live hreflang tags on 25 October 2026. Check current storefront URLs before later runs.

### Results

The default dataset has one row per input URL. requestedUrl, finalUrl, status and chain record HTTP evidence. canonicals, hreflang, robots and references hold extracted annotations and verification results. sha256 identifies the raw response body. targetCoverage shows declared, selected and verified target counts. An empty issues list means no findings within the performed checks; it is not a complete SEO certification.

REPORT.json contains full evidence, REPORT.csv contains summary rows, and REPORT.html is an escaped human-readable report. Find these in the run Output or Storage tabs.

### Interpreting findings

FETCH_INCOMPLETE, TARGET_UNVERIFIED and TARGET_LIMIT_REACHED indicate incomplete coverage. They are not proof of a broken storefront. HTTP_BLOCKED_OR_UNAVAILABLE covers 403, 429 and server errors. CANONICAL_TRAILING_SLASH_DIFFERENCE is a specific consistency review, separate from CANONICAL_NOT_SELF. Missing hreflang can be intentional. If verification is off, TARGET_VERIFICATION_DISABLED is recorded explicitly.

### Scope and limits

Raw HTTP HTML only, from the Actor server location. No JavaScript rendering, regional IP simulation, residential proxy, cookie persistence, HTTP Link-header SEO parsing or sitemap inspection. A bot-challenge page returning 200 needs human review. Canonical and reciprocal comparisons use exact URL strings; language codes are checked heuristically. At most 30 target references per page, 10 redirects and 2 MB per response. Default socket timeout is 20 seconds. Set an overall run timeout such as 180 seconds and a cost cap in Apify.

The Actor connects directly to validated public IP addresses while retaining HTTPS hostname verification and SNI, checks destinations again on every connection, and disables environment proxies. TLS validation stays enabled. These controls reduce private-network and DNS-rebinding risk; infrastructure-level outbound isolation remains recommended for public deployment.

### Cost

No paid third-party service or proxy is required. Apify charges platform usage against your available credit according to your plan; a request cap is not a monetary guarantee. Sample runs on 25 October 2026 used approximately $0.001–$0.002 each, excluding builds, based on rounded Console figures. Costs vary. No plan upgrade or paid listing is needed to test privately.

### Validation and development

Python 3.12. Run `python -m unittest discover -s tests -v` and `python main.py INPUT.json`. Local audits and tests use the standard library; cloud storage uses Apify SDK 3.4.1. Thirteen tests cover redirect loops, request/byte limits, blocks, reciprocal links, output escaping, explicit-region priority and connection-time destination validation. The cloud build runs tests before deployment.

This is recreated software version 0.3.1, not a recovery of the original conversation's files. The Console source version can differ from the software version. All 28 runtime package versions are pinned in requirements.lock.txt, based on the successful Linux/Python 3.12 cloud build. Docker installs without dependency resolution and runs pip check. The base image is digest-pinned. This is a version lock; wheel hashes are not included. Choose a source-code license and support contact before public distribution.

# Actor input Schema

## `startUrls` (type: `array`):

Up to 20 exact public storefront URLs. No region path is assumed to exist.

## `maxRequests` (type: `integer`):

Includes redirects and linked target checks. 1–200; this caps requests, not monetary cost.

## `verifyTargets` (type: `boolean`):

Check target responses and hreflang return links, subject to the request budget.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.glossier.com/en-ca"
    },
    {
      "url": "https://www.glossier.com/en-lk"
    },
    {
      "url": "https://skims.com/"
    }
  ],
  "maxRequests": 60,
  "verifyTargets": true
}
```

# Actor output Schema

## `pages` (type: `string`):

No description

## `htmlReport` (type: `string`):

No description

## `jsonReport` (type: `string`):

No description

## `csvReport` (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 = {
    "startUrls": [
        {
            "url": "https://www.glossier.com/en-ca"
        },
        {
            "url": "https://www.glossier.com/en-lk"
        },
        {
            "url": "https://skims.com/"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("dushan219/marketcheck-regional-seo-audit").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 = { "startUrls": [
        { "url": "https://www.glossier.com/en-ca" },
        { "url": "https://www.glossier.com/en-lk" },
        { "url": "https://skims.com/" },
    ] }

# Run the Actor and wait for it to finish
run = client.actor("dushan219/marketcheck-regional-seo-audit").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 '{
  "startUrls": [
    {
      "url": "https://www.glossier.com/en-ca"
    },
    {
      "url": "https://www.glossier.com/en-lk"
    },
    {
      "url": "https://skims.com/"
    }
  ]
}' |
apify call dushan219/marketcheck-regional-seo-audit --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,dushan219/marketcheck-regional-seo-audit"
        }
    }
}
```

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/TZZilNGmYuyhHmq8b/builds/CaU2xb86EgRr9VzzV/openapi.json
