# VerniciSpray Spain Products Scraper (`automation-lab/vernicispray-spain-product-catalog`) Actor

Extract Spanish VerniciSpray product titles, descriptions, specifications and image links from supplied category or product URLs for catalog enrichment.

- **URL**: https://apify.com/automation-lab/vernicispray-spain-product-catalog.md
- **Developed by:** [Automation Lab](https://apify.com/automation-lab) (community)
- **Categories:** E-commerce
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.85 / 1,000 item extracteds

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

## VerniciSpray Spain Products Scraper

Refresh **VerniciSpray products** descriptions, technical characteristics and image links for catalog enrichment. Supply Spanish category or product URLs from VerniciSpray.es and receive one structured record per distinct product/variant URL.

This independent Actor is not affiliated with or endorsed by VerniciSpray, its brands or Apify. Source names are used only to identify the supported catalog.

### What does it extract?

| Field | Meaning |
|---|---|
| `url` | Spanish source product URL |
| `productId` | Source product and variant IDs |
| `sku` | Product code, or null |
| `title` | Full product heading |
| `subtitle` | Secondary heading, or null |
| `description` | Product information tabs as whitespace-normalized text |
| `descriptionHtml` | Original information-tab markup, parsed from the page |
| `specifications` | Source characteristic labels and values |
| `imageUrls` | Original gallery/structured image links |
| `brand` | Brand when available, otherwise null |
| `category` | Spanish category when available, otherwise null |
| `scrapedAt` | UTC extraction time |

Prices, ratings, customer reviews and reviewer identities are not included. Image links can include multiple source resolutions. Images are not downloaded, edited or rehosted. Description markup is untrusted: sanitize it before rendering in your application. No translation, specification inference or generative AI is used.

### Who is it for?

- Merchants refreshing Spanish paint descriptions and characteristics in a product information system.
- Catalog teams collecting image references and matching products by source code.
- Data engineers exporting repeatable source records into a spreadsheet or warehouse.

### Why use this Actor?

It keeps the scope narrow: source titles, descriptions, product characteristics and images, without commercial or review collection. Category and explicit-product inputs share the same parser. Product IDs deduplicate overlapping URLs within one run, and source Spanish accents are decoded using the upstream character encoding.

### Get started

1. Copy a public Spanish category or product URL from VerniciSpray.es.
2. Paste it into **Spanish category or product URLs**.
3. Set the maximum products and catalog pages for your task.
4. Run the Actor and inspect its default dataset.
5. Export JSON or CSV using Apify's dataset export tools.

```json
{
  "startUrls": [{"url": "https://www.vernicispray.es/13-pinturas-en-aerosol-para-alta-temperatura.jsp"}],
  "maxItems": 20,
  "maxPages": 100
}
```

### Input parameters

| Parameter | Default | Behavior |
|---|---|---|
| `startUrls` | Required | 1–100 public HTTPS category/product URLs from vernicispray.es or www.vernicispray.es, without query parameters |
| `maxItems` | 20 | Global distinct product limit, 1–5000; zero is invalid |
| `maxPages` | 100 | Global successful category/detail fetch limit, 1–10000; excludes robots and retry requests |

Only GET requests are supported. Non-GET methods and nonempty custom payload, headers or userData in request-list entries are rejected; these editor/MCP fields cannot customize this scraper.

The earlier of the item, page or platform charge limit stops collection. A category discovers the products linked in its product list, not products from unrelated navigation or recommendation panels. Product URLs extract only their requested variant. No query search, account access, color-code lookup, automatic site-wide crawl or pagination beyond the supplied category page is provided. This Actor does not claim an exhaustive SKU catalog.

### VerniciSpray products output example

A shortened real source record:

```json
{
  "url": "https://www.vernicispray.es/p-311-0-pintura-spray-alta-temperatura-black-high-temperature.jsp",
  "productId": "311-0",
  "sku": "08008",
  "title": "Tubo Alta Temperatura: Pintura en aerosol con resistencia al calor hasta 800°C Black High Temperature",
  "specifications": [{"name": "Formato", "value": "Aerosol 400 ml"}],
  "imageUrls": ["https://www.vernicispray.es/cache_600_1/08.jpg"],
  "brand": "MACOTA",
  "category": "Pinturas en aerosol para Alta Temperatura"
}
```

The actual record includes all documented fields, longer descriptive text and additional source specifications/images. A missing structured property value remains null; absent optional brand/SKU fields remain null rather than invented.

### How much does it cost to extract VerniciSpray products?

Pay per event: a **$0.005 start fee** plus a per-product `item` event for each delivered dataset record. BRONZE pricing is **$0.00308 per product**. There is no separate charge for description text, specifications or image links.

| Tier | Per product |
|---|---:|
| FREE | $0.003542 |
| BRONZE | $0.00308 |
| SILVER | $0.0024024 |
| GOLD | $0.001848 |
| PLATINUM | $0.001848 |
| DIAMOND | $0.001848 |

At the BRONZE rate, estimated event totals are $0.00808 for one product, $0.0358 for ten and $0.313 for 100. Your qualifying aggregate monthly Apify Store spend determines your discount tier, not the volume in this one Actor. See the active pricing panel for all tiers. Platform usage charges may also apply under your Apify plan. A valid empty category can incur the start fee without product charges.

Price examples are estimates, not guaranteed invoices or payouts. Adjustments, refunds, fraud, disputes, taxes, corrections and contractual clawbacks can affect eventual billing or payout.

### Limits and failure behavior

Requests are sequential and at least one second apart. Network failures, 429 and server errors get at most three attempts with bounded backoff. Permanent HTTP errors and unsupported page shapes fail the run; existing rows are partial output, not proof of a complete successful extraction. There is no automatic paid proxy or browser fallback.

The current robots.txt policy is fetched once per run and enforced. If it cannot be fetched, the run fails closed. Search and private/transactional endpoints are excluded. A maxPages warning means the selected scope was only partially fetched: raise the cap or supply fewer URLs. Source layout and availability can change.

### Integrations

- Export CSV from the dataset into Excel or Google Sheets; flatten the specifications array downstream when needed.
- Feed JSON into a PIM or warehouse keyed by `productId`/`sku` and retain `url` for provenance.
- Schedule the same input in Apify and compare snapshots downstream. The Actor does not itself monitor changes, send alerts or maintain historical state.
- Use an Apify webhook to trigger a downstream workflow after a successful run.

### Export JSON and CSV

The default dataset is the primary output. JSON preserves nested specifications and image arrays. For CSV, choose columns in Apify's export interface or flatten arrays downstream; the Actor does not create custom SKU folders or upload records to a shop. Preserve the source URL and scrape timestamp alongside exports so updates remain traceable.

### API usage

Use your Apify token securely. Do not place it in stored URLs or shared logs.

#### cURL

```bash
curl -X POST 'https://api.apify.com/v2/acts/automation-lab~vernicispray-spain-product-catalog/run-sync-get-dataset-items' \
  -H "Authorization: Bearer $APIFY_TOKEN" -H 'Content-Type: application/json' \
  -d '{"startUrls":[{"url":"https://www.vernicispray.es/13-pinturas-en-aerosol-para-alta-temperatura.jsp"}],"maxItems":5}'
```

#### JavaScript

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/vernicispray-spain-product-catalog').call({
  startUrls: [{ url: 'https://www.vernicispray.es/13-pinturas-en-aerosol-para-alta-temperatura.jsp' }],
  maxItems: 5,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems({ limit: 5 });
console.log(items);
```

#### Python

```python
import os
from apify_client import ApifyClient
client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('automation-lab/vernicispray-spain-product-catalog').call(run_input={
    'startUrls': [{'url': 'https://www.vernicispray.es/13-pinturas-en-aerosol-para-alta-temperatura.jsp'}],
    'maxItems': 5,
})
items = client.dataset(run['defaultDatasetId']).list_items(limit=5).items
```

### MCP usage

#### Claude Code

```bash
claude mcp add --transport http apify "https://mcp.apify.com?tools=automation-lab/vernicispray-spain-product-catalog"
```

#### Claude Desktop, Cursor and VS Code

Use your client's HTTP MCP configuration and authentication setup:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=automation-lab/vernicispray-spain-product-catalog"
    }
  }
}
```

Example prompt: “Extract five products from this VerniciSpray.es category and show titles, specifications and image links. Do not collect prices or reviews.”

**Hosted input limitation:** the generated request-list editor/tool schema may expose HTTP methods and custom payload, headers or userData options that this Actor does not support; its description may omit the GET-only warning. Supply only `{ "url": "https://www.vernicispray.es/...jsp" }` entries (optional `method: "GET"`), leaving custom options absent. Runtime validation rejects unsupported options before fetching products or charging the start event. The examples above are the supported contract, not the generic editor's customization promises.

Discover actual tools and schemas with scoped `tools/list`. Actor selection also exposes run and storage helper tools; discovery alone does not authorize execution. Start once, keep the returned run/storage IDs, and follow the same run if it is pending. Use bounded backoff of 2, 4, 8 then at most 10 seconds with a 120-second total deadline; report pending at the deadline rather than starting a duplicate run. Configure your client timeout above its selected server wait plus transport margin.

After success, call `get-dataset-items` with the same run's returned `defaultDatasetId`. Using the argument names/types from scoped `tools/list`, request untransformed JSON with explicit `offset: 0`, `limit: 20` and `fields: ["url", "productId", "title", "description", "specifications", "imageUrls"]`. Advance the source offset by each admitted source page, not by a filtered/transformed row count, and stop at exhaustion or the cumulative budget. Read at most 100 rows and 64 KiB of serialized UTF-8 results admitted to model context, whichever comes first. Enforce bytes host-side; summarize or omit oversized rows with disclosure. If your client cannot intercept responses, do not assume that byte ceiling is guaranteed. Track offsets and report truncation/continuation. Keep full exports downstream, outside model context. Failed runs can contain partial rows and must not be presented as complete.

### Legality, responsible use and data handling

Use only public data you are entitled to collect and reuse. Public accessibility does not confer rights to republish descriptions or images; verify licenses and source conditions for your use. Respect the enforced robots policy and conservative request rate. Apify's standard terms apply; this Actor adds no custom end-user agreement.

Input URLs and public product text are processed on Apify and written to your run's dataset. The Actor keeps no persistent global catalog or cookie store. Dataset/input/log retention follows your Apify account/storage policies; delete the relevant run storage through Apify when no longer needed.

Failed operations send sanitized diagnostic input, exceptions and actor/build/run IDs to our private GlitchTip service for repair. Secret fields and URL queries are removed and reports are retained for 30 days. No product data is sent to an AI provider. Apify hosts execution/storage; our private GlitchTip handles sanitized diagnostics. Optional downstream integrations are controlled by you.

### FAQ and troubleshooting

**Why is my URL rejected?** Only public Spanish category/product paths are supported. Remove query parameters; do not supply search, account, color-code or non-Spanish domains.

**Why do I see fewer products?** The category may naturally contain few links, or an item/page/charge limit stopped the run. Check the final log and status before treating rows as complete.

**Are technical values standardized?** No. Labels, units and text remain source data. Missing values are null. Normalize them downstream if needed.

**Can I obtain full-resolution images?** The Actor returns the URLs actually published in the gallery/structured data, including source resolutions. It does not guess larger URLs.

**What happens after an upstream failure?** Transient failures retry boundedly. Exhaustion or an unrecognized layout fails honestly; rows already saved are partial. Try again later if the source is unavailable and report recurring issues.

### Related workflows and support

This is a standalone, source-specific catalog extractor. Other merchants' product Actors are not substitutes for VerniciSpray coverage. Use Apify datasets, schedules and integrations for your downstream enrichment workflow.

For help, open an Actor issue with a public source URL, run link and expected missing fields. Never share credentials or private personal data. We aim to provide a substantive response to user-reported issues within 14 calendar days.

# Changelog

This Actor's version history is a separate document: https://apify.com/automation-lab/vernicispray-spain-product-catalog/changelog.md

# Actor input Schema

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

Supply 1–100 HTTPS VerniciSpray.es category or product URLs without query parameters. Category pages discover their linked products; explicit product URLs extract only that product. Search, account, color-lookup and other sites are rejected. Current robots.txt is enforced. Only GET is supported; non-GET methods and nonempty custom payload, headers or userData are rejected.

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

Global maximum distinct product records across all supplied URLs, after product-ID deduplication. Default 20; 1–5000. Zero is invalid. Stops fetching when reached; does not promise complete site coverage.

## `maxPages` (type: `integer`):

Global successful category/detail page fetch limit, default 100, excluding robots.txt and retries. 1–10000; zero invalid. The earlier of maxItems, maxPages or the platform charge limit stops collection. Reaching this cap leaves partial output and a warning.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.vernicispray.es/13-pinturas-en-aerosol-para-alta-temperatura.jsp"
    }
  ],
  "maxItems": 20,
  "maxPages": 20
}
```

# Actor output Schema

## `dataset` (type: `string`):

Product rows, exportable to JSON or CSV through the dataset.

# 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.vernicispray.es/13-pinturas-en-aerosol-para-alta-temperatura.jsp"
        }
    ],
    "maxPages": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/vernicispray-spain-product-catalog").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.vernicispray.es/13-pinturas-en-aerosol-para-alta-temperatura.jsp" }],
    "maxPages": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/vernicispray-spain-product-catalog").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.vernicispray.es/13-pinturas-en-aerosol-para-alta-temperatura.jsp"
    }
  ],
  "maxPages": 20
}' |
apify call automation-lab/vernicispray-spain-product-catalog --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation-lab/vernicispray-spain-product-catalog"
        }
    }
}
```

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/ntIWEgNYGYUi03p5c/builds/jRfR8aM4dyEoKC6fy/openapi.json
