# Pubchem Compound Scraper (`real-estate-api/pubchem-compound-scraper`) Actor

PubChem Compound Scraper is a Python tool designed to query the NIH PubChem PUG REST API. It extracts chemical structures, molecular properties, identifiers (CIDs), and safety summaries into structured formats for chemical and pharmaceutical research

- **URL**: https://apify.com/real-estate-api/pubchem-compound-scraper.md
- **Developed by:** [real-estate-api](https://apify.com/real-estate-api) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.99 / 1,000 results

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

## PubChem Compound Scraper: Chemical Compound Properties by Name

<p align="center">
  <img src="https://imgur.com/rh2wLmo.png" alt="PubChem Compound Scraper" width="800" />
</p>

### Features

- **Compound lookup:** Search by common chemical names, such as aspirin or caffeine.
- **CID lookup:** Retrieve available properties using existing PubChem Compound IDs.
- **Synonym collection:** Optionally collect synonyms associated with each saved CID.
- **Structured exports:** Organize results for JSON, CSV, or Excel workflows.
- **Duplicate handling:** Store duplicate CIDs only once.
- **Error handling:** Record failed lookups without stopping the remaining inputs.
- **Request throttling:** Pace requests to reduce the risk of rate-limit errors.
- **Retry handling:** Retry HTTP 429 responses, server errors, and timeouts.
- **Execution limits:** Configure the maximum number of records and runtime.

### Use Cases

- **Compound research:** Collect properties for lists of common chemical names.
- **CID refresh:** Retrieve molecular formulas and molecular weights for known CIDs.
- **Synonym matching:** Obtain alternate compound names for matching and data enrichment.
- **Scheduled exports:** Refresh compound datasets periodically.
- **Cheminformatics preparation:** Store SMILES and InChIKey values for downstream molecular structure workflows.

### Input Parameters

| Parameter | Type | Default | Description |
|---|---|---|---|
| `names` | Array | `["aspirin"]` | Compound names to look up. |
| `cids` | Array | `[]` | PubChem Compound IDs containing digits only. |
| `includeSynonyms` | Boolean | `false` | Include synonym lists for saved compounds. |
| `maxItems` | Integer | `100` | Maximum number of compound records to save. Maximum: 1,000. |
| `timeoutSecs` | Integer | `300` | Maximum execution time in seconds. |
| `requestTimeoutSecs` | Integer | `30` | Timeout for an individual request, in seconds. |

Names and CIDs are optional lists. Both can be supplied in the same run.

### Example Input

```json
{
  "names": ["aspirin"],
  "cids": [],
  "includeSynonyms": false,
  "maxItems": 100,
  "timeoutSecs": 300,
  "requestTimeoutSecs": 30
}
```

### Output

Each compound is saved as a separate dataset record. If a name or CID cannot be processed, the scraper records an error row and continues with the remaining inputs.

#### Example Output

```json
{
  "CID": 2244,
  "MolecularFormula": "C9H8O4",
  "MolecularWeight": "180.16",
  "ConnectivitySMILES": "CC(=O)OC1=CC=CC=C1C(=O)O",
  "InChIKey": "BSYNRYMUTXBXSQ-UHFFFAOYSA-N",
  "IUPACName": "2-acetyloxybenzoic acid",
  "XLogP": 1.2,
  "scrapedAt": "2026-10-12T00:00:00+00:00"
}
```

#### Output Fields

| Field | Type | Description |
|---|---|---|
| `CID` | Integer | PubChem Compound ID. |
| `MolecularFormula` | String | Molecular formula of the compound. |
| `MolecularWeight` | String | Molecular weight as returned by PubChem. |
| `ConnectivitySMILES` | String | Connectivity SMILES representation. Name lookups request CanonicalSMILES, which PubChem may return as ConnectivitySMILES. |
| `InChIKey` | String | InChIKey returned for name-based lookups. |
| `IUPACName` | String | IUPAC name returned for name-based lookups. |
| `XLogP` | Number | XLogP value returned for name-based lookups. |
| `synonymList` | Array | Synonyms associated with the compound when enabled. |
| `scrapedAt` | String | UTC timestamp indicating when the record was saved. |
| `error` | String | Error description, present only when an input fails. |
| `input` | String | Name or CID associated with a failed lookup. |

**Note:** CID-based lookups retrieve molecular formula and molecular weight. Name-based lookups request additional properties, including SMILES, InChIKey, IUPAC name, and XLogP. If multiple inputs resolve to the same CID, that compound is stored once.

### How It Works

1. Reads the supplied compound names and CIDs.
2. Validates that at least one input list contains entries. If both lists are empty, it saves an error record and finishes.
3. Retrieves synonyms for saved CIDs when `includeSynonyms` is enabled.
4. Paces requests at approximately four requests per second.
5. Retries HTTP 429 responses, HTTP 5xx errors, and timeouts up to three times, using increasing wait periods of 2, 4, and 8 seconds or a longer delay when specified by `Retry-After`.
6. Maps returned SMILES values to the appropriate output field and removes HTML tags where necessary.
7. Stops when the configured record limit or execution time is reached.

### Limits and Terms

- Follow PubChem's published request-rate and service-usage limits, including limits of five requests per second and 400 requests per minute.
- This scraper paces requests at approximately four requests per second.
- PubChem also documents restrictions on total request-processing time within a minute.
- The maximum `maxItems` value is 1,000.
- NCBI makes PubChem data available in the public domain. Cite PubChem when republishing records and check the applicable guidance for your intended use.

### FAQ

**Can I search by name and CID in the same run?**

Yes. Both input lists can be supplied together. Duplicate CIDs are stored only once.

**Why are SMILES, XLogP, or IUPAC names missing from a CID-based record?**

CID lookups use a shorter property list that retrieves molecular formula and molecular weight. Use name-based lookups when you need the additional properties.

**What is the maximum number of compounds per run?**

The default limit is 100 records, and the maximum allowed value is 1,000.

**What happens when a compound name is unknown?**

The scraper saves an error record for that input and continues processing the remaining list.

**Can I collect synonyms?**

Yes. Set `includeSynonyms` to `true` to request synonym lists for saved compounds.

### Trademark Notice

PubChem and related names, logos, and trademarks belong to their respective owners. Their use in this documentation is solely to identify the data source and does not imply affiliation, sponsorship, endorsement, or partnership.

### Disclaimer

This scraper is an independent tool and is not affiliated with, endorsed by, sponsored by, or officially associated with PubChem or its owners. Users are responsible for complying with applicable terms, request limits, attribution requirements, and licensing conditions.

### Is Web Scraping Legal?

Collecting information that is already public is generally legal. Scraping is not the same thing as hacking, and there is no single law that bans it. The limits are the usual ones: do not break into accounts, do not take private or confidential data, and be careful with personal data and copyrighted works. A site's terms can also restrict how you access it. Facts such as a public name, price, or rating are not the same thing as republishing someone's article or photo.
This scraper collects compound information without logging in or bypassing access controls.

For a longer explanation, see Apify's article [Is web scraping legal?](https://blog.apify.com/is-web-scraping-legal/).

# Actor input Schema

## `names` (type: `array`):

Compound names to look up on PubChem, one name per line. Aspirin is the default so a first run returns a real record.

## `cids` (type: `array`):

PubChem compound IDs (CIDs) to look up. Leave empty to search by name only. Digits only, one CID per line.

## `includeSynonyms` (type: `boolean`):

Also fetch the synonym list for each CID that is returned. Off by default because some compounds have very long synonym lists.

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

Maximum number of compound records to save. Free cap, hard max 1000.

## `timeoutSecs` (type: `integer`):

Maximum seconds the run may spend fetching compounds before it stops and saves what it has.

## `requestTimeoutSecs` (type: `integer`):

Seconds to wait for a single PubChem response before retrying that request.

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

Optional proxy for PubChem requests. Default is no proxy, which matches the public PUG REST service. Turn on Apify Proxy only if your network blocks NCBI.

## Actor input object example

```json
{
  "names": [
    "aspirin",
    "caffeine"
  ],
  "cids": [
    "2244"
  ],
  "includeSynonyms": false,
  "maxItems": 100,
  "timeoutSecs": 300,
  "requestTimeoutSecs": 30,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `datasetUrl` (type: `string`):

Default dataset API URL for this run.

## `overviewUrl` (type: `string`):

Dataset items in the overview table view.

# 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 = {
    "names": [
        "aspirin"
    ],
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("real-estate-api/pubchem-compound-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 = {
    "names": ["aspirin"],
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("real-estate-api/pubchem-compound-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 '{
  "names": [
    "aspirin"
  ],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call real-estate-api/pubchem-compound-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,real-estate-api/pubchem-compound-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/k1h8fVzeBJQerA7Gh/builds/MGcv6cTTDq0CXcTib/openapi.json
