# Cdiscount Manufacturer Contact Scraper - Brand Emails (`s-r/cdiscount-contacts`) Actor

Search Cdiscount by keyword and get the manufacturer behind each product: company name, postal address and contact email, published under EU product safety rules. Every address is checked over DNS. Repeated manufacturers collapse to one row.

- **URL**: https://apify.com/s-r/cdiscount-contacts.md
- **Developed by:** [SR](https://apify.com/s-r) (community)
- **Categories:** Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $10.00 / 1,000 manufacturer contacts

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

## Cdiscount Manufacturer Contact Scraper

Search Cdiscount by keyword and get the manufacturer behind each product: company name, postal address and contact email, every address validated over DNS.

This Actor turns a product search on France's second-largest marketplace into a list of reachable brand contacts. You give it keywords, it walks the search results, opens the product pages behind them and returns one row per manufacturer with the contact details Cdiscount publishes, plus a verification block for the email.

### Manufacturer, not seller. The difference matters

Cdiscount publishes **no email for its marketplace sellers**. A product page carries `sellerId`, `sellerName` and a rating block, and no address of any kind. If you came here looking for seller emails, no tool can give you those from Cdiscount, because Cdiscount does not have them on the page.

What it does publish is the **manufacturer's** contact, because the EU General Product Safety Regulation obliges a brand placing goods on the EU market to be reachable, and the marketplace has to surface it.

Those are genuinely different parties. In testing, seller "Aosom France" was selling a product manufactured by "MH France", and the contact returned is MH France's. Each row carries both, named separately, so you always know whose address you have.

### What you get

| Field | Example |
|---|---|
| `manufacturer_name` | MH France |
| `manufacturer_email` | contactcd@mhfrance.fr |
| `manufacturer_address` | postal address as published |
| `seller_name` | Aosom France |
| `seller_id`, `seller_rating`, `seller_sales_count` | the marketplace seller |
| `product_title`, `product_url` | where the contact was found |
| `verification` | format, domain, MX, role account, free provider, disposable, business domain, status |

### Why scrape Cdiscount manufacturer contacts

Supplier discovery normally runs the wrong way round. You start from a directory of companies and hope some of them sell what you need. Starting from a product search inverts it: you search the category you actually care about, and every contact that comes back demonstrably already sells that product in France.

The second reason is that this data is only reachable per product page. There is no export, no supplier directory and no API on Cdiscount that lists manufacturers, so the alternative to this Actor is opening listings by hand and copying French postal addresses out of a compliance panel.

Third, the contacts are compliance data rather than scraped personal addresses. GPSR exists so that a regulator, a retailer or a customer can reach the responsible company. That makes it a clean basis for B2B research, and it also means the same field is present across categories rather than only where a brand chose to publish it.

### Input

| Field | Type | Required | What it does | Default |
|---|---|---|---|---|
| `keywords` | array | yes | Product keywords to search. Each result page is walked and the products behind it are read. | `["tapis de yoga"]` |
| `products_per_keyword` | integer | no | How many listings to open per keyword, 1 to 60. | `20` |
| `max_products` | integer | no | Hard ceiling on product pages read in one run. This is your cost ceiling. | `50` |
| `only_products_with_contact` | boolean | no | Return only rows that carry a contact, so you pay for leads rather than for pages. | `true` |
| `verify_emails` | boolean | no | Check format and look up the domain's MX records over DNS. | `true` |

### Output

```json
{
  "manufacturer_name": "MH FRANCE",
  "manufacturer_email": "contactcd@mhfrance.fr",
  "manufacturer_address": "12 rue de l'Industrie, 59200 Tourcoing, France",
  "seller_name": "Aosom France",
  "seller_id": 12345,
  "seller_rating": 4.4,
  "seller_sales_count": 18204,
  "product_title": "Tapis de yoga antidérapant 183 x 61 cm",
  "product_url": "https://www.cdiscount.com/...",
  "verification": {
    "email": "contactcd@mhfrance.fr",
    "valid_format": true,
    "domain": "mhfrance.fr",
    "has_mx": true,
    "is_role_account": true,
    "is_free_provider": false,
    "is_disposable": false,
    "is_business_domain": true,
    "status": "valid"
  }
}
```

### One contact, one row

A single manufacturer often sits behind many listings: one brand supplied three of five rows in testing. Repeated contacts are collapsed to one row. A repeated contact is not an extra lead, and since a row is the billable unit, charging three times for it would be charging three times for the same fact.

### Use cases

**Supplier sourcing for a category.** A buyer entering a category searches the five product terms that define it and gets the brands behind the listings that already sell in France, with a postal address to check company registration against. The seller fields stay in the row, so you can also see which marketplace accounts carry each brand.

**Competitive brand mapping.** Retail and pricing teams know which sellers hold a category but rarely know which manufacturers sit behind them, because the seller name on a listing is usually a reseller. Running the same keyword set weekly shows which brands enter and leave a category.

**Compliance and due diligence.** GPSR requires a reachable responsible party. If you operate a marketplace or import goods, this gives you the published contact for each product, plus a DNS check that says whether that address can actually receive mail.

**Lead lists that survive validation.** Because every row is deduplicated and MX-checked, the list you export does not need a second pass through a verification tool before a campaign.

### Limits and gotchas

- **France only.** This reads cdiscount.com, which is a French marketplace. Keywords work best in French.
- **Roughly half of Cdiscount's own search results point at products that no longer resolve**, answering 404 or 410. That is Cdiscount's data, not a fetch problem, and those URLs are abandoned immediately rather than retried. Ask for roughly twice as many products as you need.
- **Of the product pages that loaded, 83% carried a manufacturer email.** The rest publish a company name and address with no address for mail.
- **No seller emails exist.** See the section above. A row's `seller_*` fields identify the marketplace account, not a contact.
- **A failed DNS lookup returns `has_mx: null` and `status: "unknown"`, never `false`.** A resolver timeout is not evidence that a domain cannot receive mail.
- **No mail is sent and nothing notifies the manufacturer.** Verification is format plus MX records only.
- **`max_products` is the cost ceiling**, and it is counted in pages opened rather than rows returned, because a page that turns out to carry no contact still had to be read.

### Pricing

Pay per event: you are charged per contact row delivered, not per compute unit and not per page read. With `only_products_with_contact` left on, that means you pay for rows that carry a manufacturer contact. There is no actor-start fee and no per-compute-unit charge.

### FAQ

**Can I get Cdiscount seller emails?** No, and neither can any other tool. Cdiscount does not publish an email or address for marketplace sellers. It publishes the manufacturer's, which is what this Actor returns.

**Why is the manufacturer different from the seller?** Most listings are placed by resellers. The manufacturer is the company that put the product on the EU market and is legally reachable for it.

**How do I find manufacturer contacts for a whole category?** Search the four or five keywords that define the category and raise `products_per_keyword`. Contacts repeat across listings and are collapsed, so a wide search returns fewer rows than pages.

**Are the email addresses verified?** Format is checked and the domain's MX records are looked up over DNS. That proves the domain can receive mail; it does not prove the mailbox exists.

**Is scraping manufacturer contact details from Cdiscount lawful?** These details are published because EU product safety law requires it, and they identify businesses rather than private individuals. Use them for B2B research, supplier discovery, compliance and due diligence, and follow the marketing and data-protection rules that apply where you operate.

### Related Actors

- [Free email verifier](https://apify.com/s-r/free-email-verifier---verify-email-address) to re-check a list you already hold.
- [Free email domain scraper](https://apify.com/s-r/free-email-domain-scraper) to find addresses on a company's own website.
- [Free LinkedIn company finder](https://apify.com/s-r/free-linkedin-company-finder---linkedin-address-from-any-site) to match a manufacturer to its LinkedIn page.

# Actor input Schema

## `keywords` (type: `array`):

Product keywords to search on Cdiscount. Each result page is walked and the products behind it are read.

## `products_per_keyword` (type: `integer`):

How many listings to open per keyword. Roughly half of Cdiscount's own search results point at products that no longer resolve, so ask for about twice what you need.

## `max_products` (type: `integer`):

Hard ceiling on product pages read in one run. This is your cost ceiling.

## `only_products_with_contact` (type: `boolean`):

On by default, so you pay only for rows that carry a contact. Repeated manufacturers are collapsed to one row either way.

## `verify_emails` (type: `boolean`):

Check format and look up the domain's MX records over DNS. No mail is sent and nothing notifies the manufacturer.

## Actor input object example

```json
{
  "keywords": [
    "tapis de yoga"
  ],
  "products_per_keyword": 20,
  "max_products": 50,
  "only_products_with_contact": true,
  "verify_emails": true
}
```

# Actor output Schema

## `contacts` (type: `string`):

One row per manufacturer.

## `summary` (type: `string`):

Counts, hit rate and fetch stats.

# 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 = {
    "keywords": [
        "tapis de yoga"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("s-r/cdiscount-contacts").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 = { "keywords": ["tapis de yoga"] }

# Run the Actor and wait for it to finish
run = client.actor("s-r/cdiscount-contacts").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 '{
  "keywords": [
    "tapis de yoga"
  ]
}' |
apify call s-r/cdiscount-contacts --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,s-r/cdiscount-contacts"
        }
    }
}
```

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/LCPPnhhLqtcaSt8xs/builds/yuWEdimcEP8JcOG39/openapi.json
