# PressCity Scraper — Used Printing Equipment (`crawloop/presscity-scraper`) Actor

Scrape PressCity used printing presses, postpress, prepress, digital, and packaging machines: specs, year, sheet size, impressions, images, dealer profiles. Category crawl, keyword search, or startUrls. Listings or details mode. Fast HTTP via curl_cffi.

- **URL**: https://apify.com/crawloop/presscity-scraper.md
- **Developed by:** [Andrej Kiva](https://apify.com/crawloop) (community)
- **Categories:** E-commerce, Other
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 scraped presscity details

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?

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

## PressCity Scraper — Used Print & Packaging Machinery

> **Disclaimer:** Unofficial tool — not affiliated with, sponsored by, or endorsed by PressCity or its operators or its affiliates. Data is read from publicly accessible pages only. No login. You are responsible for complying with applicable law (including GDPR where personal data appears) and the site’s terms. No warranty on accuracy or availability. Provided for informational and research use.

> **Crawloop Print & Lab Equipment** — used presses and laboratory inventory.

| PressXchange | PressCity | Labexchange | Surplex | Troostwijk |
| :--- | :--- | :--- | :--- | :--- |
| [PressXchange Scraper](https://apify.com/crawloop/pressxchange-scraper) | **PressCity Scraper** ◄── you are here | [Labexchange Scraper](https://apify.com/crawloop/labexchange-scraper) | [Surplex Scraper](https://apify.com/crawloop/surplex-scraper) | [Troostwijk Scraper](https://apify.com/crawloop/troostwijk-scraper) |

Scrape **used graphic, print, and packaging machinery** into clean structured JSON — Heidelberg, Komori, KBA, Manroland, Bobst, Polar, Horizon, and more. Built for B2B workflows: printing equipment dealers, packaging buyers, market comps, and inventory monitoring.

Supports **group / category / manufacturer crawls**, **keyword search**, **start URLs**, and **direct machine detail pages**. Choose `listings` mode for fast card-level catalogs or `details` mode for full product pages with technical specs, JSON-LD, image galleries, and optional dealer profile enrichment.

Lightweight HTTP extraction with TLS fingerprinting — no headless browser overhead. Residential proxies recommended for production runs.

### When to use this Actor

Use the **PressCity Scraper** when you need:

- **Machine inventory** across Press, Prepress, Postpress / Bindery, Packaging, Web, Digital, and related groups
- **Technical attributes** — manufacturer, model, year, colors, sheet size, perfector, autoplate, impressions / hours, availability
- **Equipped options** — feature lists parsed from descriptions (Alcolor, Cptronic, wash-up devices, and more)
- **Image galleries** — full-size CDN photos for valuation and catalog enrichment
- **Dealer context** — company name and profile URL; optional website, address, and verified badge when `scrapeDealerDetails` is enabled
- **Keyword discovery** — search terms such as Heidelberg SM 74 or Bobst without building category URLs by hand

Ideal for printing equipment dealers, packaging buyers, market analysts, and data teams tracking used graphic-arts machinery.

### Data pipeline

```
Input                              Mode                         Output
─────────────────────────         ────────────────────         ──────────────────────────

  Group / category URL       ──►   listings (fast cards)  ──►  title, snippet, image, IDs
  Keyword search             ──►   details  (full PDP)   ──►  specs, images, description
  Direct machine URL         ──►                           ──►  manufacturer, dealer fields
  categories[] enum

  Join by manufacturer + model ──► comps & inventory alerts
```

### Key Features

- **Two extraction modes** — `listings` for card-level stubs; `details` for JSON-LD Product + specs table + gallery.
- **Print-specific specs** — colors, sheet size, perfector, autoplate, impressions, availability when published.
- **Category shortcuts** — optional top-level groups (press, prepress, postpress, packaging, web, digital, …).
- **Dealer enrichment** — optional profile fetch (website, address, zip/city, verified seller), cached per dealer.
- **Robust URL handling** — resolves canonical machine pages; skips broken legacy card links.
- **Fast concurrent HTTP** — Chrome TLS impersonation and parallel detail fetches; residential proxy recommended at scale.

### Input Parameters

| Parameter | Type | Default | Description |
| :--- | :--- | :--- | :--- |
| `startUrls` | Array | sample sheetfed URL | Search, group, category, manufacturer, or machine detail URLs. |
| `searchKeyword` | String | — | Keyword search (e.g. Heidelberg SM 74). |
| `categories` | Array | `[]` | Top-level groups when you do not paste filtered URLs. |
| `runMode` | String | `"details"` | `"listings"` (cards) or `"details"` (full PDP). |
| `scrapeDealerDetails` | Boolean | `false` | Visit dealer profiles in details mode. |
| `maxItems` | Integer | `100` | Maximum machines to return (`0` = unlimited). |
| `maxPagesPerUrl` | Integer | `5` | Pagination depth per start URL (`0` = until exhausted). |
| `concurrencyLimit` | Integer | `5` | Parallel detail workers (1–20). |
| `proxyConfiguration` | Object | Apify Proxy | Residential proxies recommended. |

#### Input example — sheetfed details

```json
{
  "startUrls": [
    { "url": "https://presscity.com/en/search/group/2/press/category/4/sheetfed/" }
  ],
  "runMode": "details",
  "scrapeDealerDetails": false,
  "maxItems": 100,
  "maxPagesPerUrl": 5,
  "concurrencyLimit": 5,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": ["RESIDENTIAL"]
  }
}
```

#### Input example — keyword search

```json
{
  "searchKeyword": "Heidelberg SM 74",
  "runMode": "details",
  "maxItems": 50,
  "maxPagesPerUrl": 3,
  "concurrencyLimit": 4,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": ["RESIDENTIAL"]
  }
}
```

### Output Format

Each row is pushed to the default dataset.

#### Details mode (enriched)

| Field | Description |
| :--- | :--- |
| `id`, `url`, `title` | Machine identifiers |
| `reference`, `manufacturer`, `model` | Equipment identity |
| `year`, `colors`, `location` | Core listing facts |
| `sheetSize`, `impressions`, `perfector`, `hasAutoplate` | Format and configuration |
| `availability`, `equippedFeatures` | Shipping window and option list |
| `price`, `priceCurrency`, `priceStatus` | Asking price or request-price status |
| `group`, `category`, `breadcrumbs` | Taxonomy |
| `description`, `images`, `imageUrl` | Free text and gallery |
| `dealerName`, `dealerProfileUrl`, `dealerWebsite`, … | Dealer block (enriched when enabled) |
| `scrapedAt` | Scrape timestamp (UTC) |

#### Example record

```json
{
  "id": "452639-457687",
  "url": "https://presscity.com/en/machines/heidelberg/452639-457687/heidelberg-sm-52-p.html",
  "title": "Heidelberg SM 52--P",
  "reference": "G-022-7707",
  "manufacturer": "Heidelberg",
  "model": "SM 52",
  "year": 1999,
  "colors": 2,
  "hasAutoplate": true,
  "perfector": "1 + 1 / 2 + 0",
  "sheetSize": "370 x 520 mm.",
  "location": "Germany",
  "impressions": "approx. 70 mio",
  "availability": "07/2026",
  "priceStatus": "request_price",
  "group": "Press",
  "category": "Sheetfed offset",
  "breadcrumbs": ["Groups", "Press", "Sheetfed offset", "Heidelberg", "SM 52"],
  "equippedFeatures": ["Autoplate", "Alcolor automatic filmdamping", "Cptronic"],
  "images": [
    "https://cdn.presscity.com/838/800/x800_heidelberg-sm52-12840975.jpg"
  ],
  "dealerName": "STC GmbH",
  "dealerProfileUrl": "https://presscity.com/en/dealers/germany/stc-gmbh/info838.html",
  "isVerifiedDealer": true,
  "scrapedAt": "2026-07-22T19:30:00Z"
}
```

### Integration examples

#### Node.js

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('crawloop/presscity-scraper').call({ startUrls: [{ url: "https://www.presscity.com/en/machines/sheetfed-offset" }], runMode: "details", maxItems: 20, proxyConfiguration: { useApifyProxy: true } });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.slice(0, 5));
```

#### Python

```python
from apify_client import ApifyClient

client = ApifyClient(token)
run = client.actor("crawloop/presscity-scraper").call(
    run_input={"startUrls": [{"url": "https://www.presscity.com/en/machines/sheetfed-offset"}], "runMode": "details", "maxItems": 20, "proxyConfiguration": {"useApifyProxy": True}}
)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item.get("title"), item.get("manufacturer"), item.get("year"))
```

#### cURL

```bash
curl "https://api.apify.com/v2/acts/crawloop~presscity-scraper/runs?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"startUrls":[{"url":"https://www.presscity.com/en/machines/sheetfed-offset"}],"runMode":"details","maxItems":20,"proxyConfiguration":{"useApifyProxy":true}}'
```

### MCP and AI assistants

Use this Actor from AI tools via [Apify MCP](https://docs.apify.com/platform/integrations/mcp). Connect your Apify account, then call `crawloop/presscity-scraper`.

Example prompts:

- "Run PressCity Scraper for sheetfed offset, details mode, max 20, return title, manufacturer, year, location"
- "Scrape PressCity used presses and summarize dealer names"
- "Chain PressCity then PressXchange Scraper to compare inventories"

### Suite next step

Compare with [PressXchange Scraper](https://apify.com/crawloop/pressxchange-scraper). For auctions, use [Troostwijk Scraper](https://apify.com/crawloop/troostwijk-scraper).

### Notes

- Most listings are **Request Price** — expect `priceStatus: "request_price"` and a null numeric `price`.
- Public enquiry forms use captcha; this Actor does not submit enquiries or scrape private contacts beyond what dealer profiles publish.
- Prefer residential proxies for larger crawls; keep concurrency moderate (3–8).
- Pagination continues past the short pager UI (pages beyond 5 still return results until empty).

# Actor input Schema

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

PressCity URLs to scrape: search/group/category/manufacturer pages, keyword search result pages, or direct machine detail pages (/en/machines/…). Filters applied on-site can be pasted here.

## `searchKeyword` (type: `string`):

Optional keyword search (e.g. 'Heidelberg SM 74', 'Bobst'). Builds /en/?q=…\&page=search and paginates via /en/search/search-term/…/page/N/.

## `categories` (type: `array`):

Optional top-level PressCity groups to crawl (in addition to startUrls / searchKeyword).

## `runMode` (type: `string`):

listings = fast card-level data from search/category pages (Store auto-test default). details = visit each machine page for specs, JSON-LD, images, dealer (needs residential; some exits return HTTP 403).

## `scrapeDealerDetails` (type: `boolean`):

When true and runMode is details, visit each dealer profile page for website, address, zip/city, and verified status. Cached per dealer.

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

Maximum machines to return. 0 = unlimited. Keep small for quick Store runs (Apify auto-test must finish in under 5 minutes).

## `maxPagesPerUrl` (type: `integer`):

Pagination depth per listing source. 0 = until exhausted.

## `concurrencyLimit` (type: `integer`):

Parallel detail-page workers (1–20).

## `proxyConfiguration` (type: `object`):

Apify Proxy. RESIDENTIAL + country DE is recommended — unpinned residential exits often return HTTP 504; datacenter IPs get HTTP 403 on machine detail pages.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://presscity.com/en/search/group/2/press/category/4/sheetfed/"
    }
  ],
  "categories": [],
  "runMode": "listings",
  "scrapeDealerDetails": false,
  "maxItems": 10,
  "maxPagesPerUrl": 1,
  "concurrencyLimit": 5,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "DE"
  }
}
```

# Actor output Schema

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

Default dataset items (machine listings or full detail records).

# 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://presscity.com/en/search/group/2/press/category/4/sheetfed/"
        }
    ],
    "runMode": "listings",
    "scrapeDealerDetails": false,
    "maxItems": 10,
    "maxPagesPerUrl": 1,
    "concurrencyLimit": 5
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawloop/presscity-scraper").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://presscity.com/en/search/group/2/press/category/4/sheetfed/" }],
    "runMode": "listings",
    "scrapeDealerDetails": False,
    "maxItems": 10,
    "maxPagesPerUrl": 1,
    "concurrencyLimit": 5,
}

# Run the Actor and wait for it to finish
run = client.actor("crawloop/presscity-scraper").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://presscity.com/en/search/group/2/press/category/4/sheetfed/"
    }
  ],
  "runMode": "listings",
  "scrapeDealerDetails": false,
  "maxItems": 10,
  "maxPagesPerUrl": 1,
  "concurrencyLimit": 5
}' |
apify call crawloop/presscity-scraper --silent --output-dataset

```

## MCP server setup

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

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/wxLqoafWtebV9QDiO/builds/qEGtgi9LcwOWCtNwj/openapi.json
