     [Blog](https://scrapfly.io/blog)   /  [python](https://scrapfly.io/blog/tag/python)   /  [How to Scrape RS-Online (rs-online.com) in 2026](https://scrapfly.io/blog/posts/how-to-scrape-rs-online)   # How to Scrape RS-Online (rs-online.com) in 2026

 by [Ziad Shamndy](https://scrapfly.io/blog/author/ziad) Jul 24, 2026 19 min read [\#python](https://scrapfly.io/blog/tag/python) [\#scrapeguide](https://scrapfly.io/blog/tag/scrapeguide) 

 [  ](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fscrapfly.io%2Fblog%2Fposts%2Fhow-to-scrape-rs-online "Share on LinkedIn") [  ](https://x.com/intent/tweet?url=https%3A%2F%2Fscrapfly.io%2Fblog%2Fposts%2Fhow-to-scrape-rs-online&text=How%20to%20Scrape%20RS-Online%20%28rs-online.com%29%20in%202026 "Share on X") [  ](https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fscrapfly.io%2Fblog%2Fposts%2Fhow-to-scrape-rs-online "Share on Facebook")    

 

 

Summarize this article with

 [  ](https://chat.openai.com/?q=Summarize%20this%20article%20and%20explain%20how%20Scrapfly%20helps%20me%20scrape%20any%20website%20at%20scale%20and%20bypass%20anti-bot%20systems%20for%20my%20use%20case%3A%20https%3A%2F%2Fscrapfly.io%2Fblog%2Fposts%2Fhow-to-scrape-rs-online) [  ](https://claude.ai/new?q=Summarize%20this%20article%20and%20explain%20how%20Scrapfly%20helps%20me%20scrape%20any%20website%20at%20scale%20and%20bypass%20anti-bot%20systems%20for%20my%20use%20case%3A%20https%3A%2F%2Fscrapfly.io%2Fblog%2Fposts%2Fhow-to-scrape-rs-online) [  ](https://x.com/i/grok?text=Summarize%20this%20article%20and%20explain%20how%20Scrapfly%20helps%20me%20scrape%20any%20website%20at%20scale%20and%20bypass%20anti-bot%20systems%20for%20my%20use%20case%3A%20https%3A%2F%2Fscrapfly.io%2Fblog%2Fposts%2Fhow-to-scrape-rs-online) [  ](https://www.perplexity.ai/search/new?q=Summarize%20this%20article%20and%20explain%20how%20Scrapfly%20helps%20me%20scrape%20any%20website%20at%20scale%20and%20bypass%20anti-bot%20systems%20for%20my%20use%20case%3A%20https%3A%2F%2Fscrapfly.io%2Fblog%2Fposts%2Fhow-to-scrape-rs-online) [  ](https://www.google.com/search?udm=50&aep=11&q=Summarize%20this%20article%20and%20explain%20how%20Scrapfly%20helps%20me%20scrape%20any%20website%20at%20scale%20and%20bypass%20anti-bot%20systems%20for%20my%20use%20case%3A%20https%3A%2F%2Fscrapfly.io%2Fblog%2Fposts%2Fhow-to-scrape-rs-online) 



         

   **Web Scraping API**Scrape any website with anti-bot bypass, proxy rotation, and JS rendering.

 

 [ Learn More  ](https://scrapfly.io/products/web-scraping-api) [  Docs ](https://scrapfly.io/docs/scrape-api/getting-started) 

 

 

Try to pull RS-Online data at scale and you learn one thing fast. "RS-Online" is not a single website. The same part shows up on us.rs-online.com, uk.rs-online.com, and de.rs-online.com at different prices, currencies, and bot defenses.

RS stocks more than 750,000 industrial and electronic products with live pricing, stock, datasheets, and specs. On the North American storefront, a plain HTTP request currently returns a DataDome challenge instead of product HTML.

This guide shows how to scrape product listings and detail pages from RS-Online's North American storefront in 2026. It also explains how RS storefronts differ by region, but the included parser does not cover the EU or Asia `/web/` sites. If you also track Mouser, the guide is its sibling.



[**RS-Online Scraper**github.com/scrapfly/scrapfly-scrapers/tree/main/rs-online-scraper](https://github.com/scrapfly/scrapfly-scrapers/tree/main/rs-online-scraper)

## Key Takeaways

- RS-Online exposes three public surfaces: category listings, keyword search, and product detail pages. Each part is keyed by its RS Stock No. and manufacturer part number (MPN).
- RS-Online is not one website. It is a network of regional storefronts (us.rs-online.com, uk.rs-online.com/web/, de.rs-online.com/web/, plus rsdelivers.com) with different prices, currencies, and URL structures.
- The maintained scraper targets the North American Magento storefront and uses Scrapfly ASP for its DataDome-protected pages. EU and Asia `/web/` storefronts require separate parser coverage and verification.
- Changing the User-Agent, headers, or request rate alone is not a reliable fix. The maintained North American example uses ASP with a US residential proxy configuration.
- Unlike Mouser and DigiKey, RS has no public product API. Partner access runs through account-gated integrations (PunchOut, cXML, EDI), so scraping the public site is the practical path.

**Get web scraping tips in your inbox**Trusted by 100K+ developers and 30K+ enterprises. Unsubscribe anytime.







## Why Scrape RS-Online?

Teams scrape RS-Online to compare component prices across distributors, monitor stock and whether lead time is required, aggregate datasheets and specs, and enrich industrial catalogs that reach well beyond electronic components.

RS Group spans power, connectors, automation, tools, and facilities, so the catalog is broad. Here are the jobs that land on scraping the public site:

- Multi-distributor price comparison and BOM cost tracking across RS, Mouser, DigiKey, and Newark.
- Stock, availability, and lead-time requirement monitoring for procurement and supply-chain teams.
- Datasheet, spec, and parametric-attribute aggregation for component-search tools.
- Competitive pricing intelligence across distributors and across RS's own regional storefronts.
- Industrial-MRO catalog enrichment beyond electronic components, covering power, connectors, automation, and tools.

RS product pages do not guarantee a datasheet link, so the extraction schema should allow a missing value.

Procurement teams have the same motive. They want to catch price and stock changes programmatically, ahead of checkout, rather than discovering them one order at a time.

The decision frame below shows why nearly every RS data job points to scraping:

| Need | Path |
|---|---|
| Broad catalog or category browsing across families | Scrape |
| Keyword search across manufacturers | Scrape |
| Parametric spec pulls for part selection | Scrape |
| Price and stock across RS regional sites | Requires storefront-specific parsers, configuration, and validation |
| Multi-distributor BOM tools (RS, Mouser, DigiKey, Newark) | Scrape |
| Account-specific contract pricing on a trade account | RS procurement integration (PunchOut/cXML) |

RS has no public product API, so for almost every use case the choice is to scrape the public site or negotiate an account-gated procurement integration.



## Does RS-Online Have a Public API?

No. RS-Online does not publish a public, self-service product-information API the way Mouser (api.mouser.com) and DigiKey (Product Information API v4) do. There is no developer portal you can sign up for.

What RS does offer is account-gated B2B eProcurement for established trade customers. That includes PunchOut, using the OCI or cXML protocols, which connects to procurement platforms like SAP Ariba and Coupa.

These integrations are documented on RS's own eProcurement pages, for example uk.rs-online.com/web/content/services/procurement-solutions/rs-eprocurement. They are built for purchasing inside a buyer's system, not for open catalog data access, and they require a negotiated account.

So what does that mean for a developer building against RS?

- If you need product, price, stock, datasheet, or parametric data and you have no negotiated RS integration, scraping the public site is the practical path.
- If you are an established RS trade customer building purchasing automation, talk to RS about PunchOut or cXML, but that is procurement plumbing rather than a catalog-data API.
- Either way, RS gives you no public REST endpoint for the catalog data this guide extracts.

Keep the claim precise. As of 2026 there is no public self-service product API, not "no API at all." Procurement integrations exist for trade accounts, while a public catalog API does not.

The rest of this guide covers the North American public storefront implemented by the maintained scraper, starting with why naive requests are unreliable.



## Why Is RS-Online Hard to Scrape?

RS storefronts use different platforms and access controls, so both request handling and parsing are region-specific.

The maintained module's implemented target is the North American `us.rs-online.com` Magento storefront. It uses Scrapfly ASP with a US residential proxy configuration. The EU and Asia `/web/` storefronts use different URLs and markup, and the current repository contains no parser, fixture, or test for them. A June 2026 UK attempt reported in the draft did not produce a successful result, so this guide does not present the Akamai path as demonstrated.

Anti-bot services can evaluate transport, browser, header, and IP signals. Changing only the User-Agent or request rate is therefore not a reliable solution. Geo-targeting and browser rendering can help retrieve the intended storefront, but they do not make a US Magento parser compatible with a different regional platform.

For the North American implementation:

- Listing pages need `render_js=True` and a pagination selector because the product grid is rendered client-side.
- Product detail pages expose JSON-LD, GA4 data, and server-rendered fields that the module parses without forcing JavaScript rendering.
- `BASE_CONFIG` enables ASP, pins `country="us"`, and uses the residential proxy pool shipped by the maintained example.

The code below follows that tested repository boundary. For more detail on the North American protection layer, see

[How to Bypass Datadome Anti Scraping in 2026Learn how Datadome detects web scrapers using TLS, IP, and ML analysis, and discover practical bypass techniques and tools for 2026.](https://scrapfly.io/blog/posts/how-to-bypass-datadome-anti-scraping)

.

## How Do RS-Online's Regional Sites and Currencies Differ?

RS operates separate regional storefronts, so the same part can have different prices, currencies, stock, and URLs by market.

| Region | Example domain | Platform | Currency | Tutorial status |
|---|---|---|---|---|
| North America | us.rs-online.com | Adobe Commerce / Magento | USD | Implemented and tested in the repository |
| UK | uk.rs-online.com/web/ | legacy `/web/` | GBP | Separate parser required |
| Germany | de.rs-online.com/web/ | legacy `/web/` | EUR | Separate parser required |
| Japan | jp.rs-online.com/web/ | legacy `/web/` | JPY | Separate parser required |
| Smaller markets | rsdelivers.com, rsonline.cn | varies | local | Separate discovery and validation required |

That distinction changes how you design a regional data pipeline:

- Choose the storefront that matches the price and inventory you need.
- Pinning a request to the target country can help retrieve the correct storefront, but it does not adapt selectors or URL construction.
- Match records across sources with a normalized `(manufacturer, MPN)` key. An RS Stock No. can differ by catalog, and an MPN alone can collide across manufacturers.
- Before adding an EU or Asia market, implement and test that storefront's listing and product parsers with representative fixtures.

The code in the rest of this tutorial stays on `us.rs-online.com` with `country="us"`. Regional storefronts are context for future extensions, not delivered behavior in the current module.



## Setting Up the Scraper

Get to a working environment first. You need Python 3.10 or newer, the Scrapfly SDK, and loguru for readable logs. Install both with one command:

shell```shell
pip install "scrapfly-sdk[all]" loguru
```



Set your API key as an environment variable so it stays out of the code:

shell```shell
export SCRAPFLY_KEY="your-scrapfly-api-key"
```



The canonical `rs-online-scraper` module ships in `scrapfly-scrapers`. It is async, built around `ScrapflyClient.concurrent_scrape()`, and covers the North American Magento storefront (`us.rs-online.com`). EU and Asia `/web/` compatibility is not implemented or demonstrated. The next two sections show non-standalone excerpts from the module; they omit shared imports, data models, client initialization, and configuration, so use the repository block above for runnable code.

You are not limited to Python either. Scrapfly ships SDKs for Python, TypeScript, Go, and Rust, plus a Scrapy integration, so a non-Python stack can follow the same approach. With the environment ready, the first surface to map is the listings.



Scrapfly

#### Scale your web scraping effortlessly

Scrapfly handles proxies, browsers, and anti-bot bypass — so you can focus on data.

[Try Free →](https://scrapfly.io/register)## How to Scrape RS-Online Search and Category Listings

RS exposes catalog listings two ways, and the exact URL shape depends on the region. On the North American Magento site, search lives at `/catalogsearch/result/` and categories at SEO-slug paths like `/connectors/d-sub-connectors-contacts-accessories/d-sub-connectors/`.

EU and Asia storefronts use different `/web/` routes, but the current module does not include or test selectors for those pages. The listing code below applies only to the North American Magento storefront.

Each North American listing row carries the fields the scraper actually extracts:

- RS Stock No., MPN, and the link to the product detail page.
- A price snapshot in the storefront currency plus the stock-badge availability text and quantity.
- A product image URL.

Brand, description, and specs are not in the listing row. They only live on the detail page, so a full record still costs a second fetch per part. Parametric category pages additionally expose the filter facets that define the search, which is how you narrow by voltage, package, or rating.

One delivery detail matters for the North American site. The category and search grid is JS-rendered, since a no-JS category fetch returned zero product cards in testing, so both surfaces need `render_js` plus a `wait_for_selector` on the pagination block.

The `rs-online-scraper` module ships this as `parse_search()`, run against each listing row:

python```python
def parse_search(response: ScrapeApiResponse) -> Dict:
    sel = response.selector
    results = []
    for row in sel.css("tr.product-item"):
        details = row.css(".product-item-details p::text").getall()
        mpn = rs_stock_number = None
        for detail in details:
            if "Manufacturer Part #:" in detail:
                mpn = detail.split("Manufacturer Part #:", 1)[1].strip()
            elif "RS Stock #:" in detail:
                rs_stock_number = detail.split("RS Stock #:", 1)[1].strip()

        price_text = " ".join(row.css(".product-price li:first-child ::text").getall())
        price_match = re.search(r"[\d,]+\.\d+", price_text)
        stock_number_text = row.css(".stock-badge__detail-number::text").get()

        results.append(RSSearchResult(
            name=row.css(".product-item-name a::text").get(),
            url=row.css(".product-item-name a::attr(href)").get(),
            rs_stock_number=rs_stock_number,
            mpn=mpn,
            price=price_match.group(0).replace(",", "") if price_match else None,
            currency=row.css(".product-price [data-currency-code]::attr(data-currency-code)").get(),
            availability=row.css(".stock-badge__label::text").get(),
            stock_quantity=int(stock_number_text.replace(",", "")) if stock_number_text else None,
            image=row.css(".product-item-photo img::attr(src)").get(),
        ))

    total_pages = 1
    page_totals = [
        int(m.group(1))
        for label in sel.css('[data-testid="pagination"] a::attr(aria-label)').getall()
        if (m := re.search(r" of (\d+)$", label))
    ]
    if page_totals:
        total_pages = max(page_totals)

    return {"results": results, "total_pages": total_pages}
```



`scrape_category()` and `scrape_search()` both call this parser on the first page, read the total page count off `[data-testid="pagination"]`, then fan the remaining pages out through `SCRAPFLY.concurrent_scrape()`:

python```python
from urllib.parse import quote_plus


async def scrape_search(query: str, max_pages: int = 3) -> List[RSSearchResult]:
    base_url = f"https://us.rs-online.com/catalogsearch/result/?q={quote_plus(query)}"

    first_page = await SCRAPFLY.async_scrape(
        ScrapeConfig(base_url, **BASE_CONFIG, render_js=True, wait_for_selector="[data-testid='pagination']")
    )
    data = parse_search(first_page)
    results, total_pages = data["results"], min(data["total_pages"], max_pages)

    if total_pages > 1:
        to_scrape = [
            ScrapeConfig(f"{base_url}&page={page}", **BASE_CONFIG, render_js=True, wait_for_selector="[data-testid='pagination']")
            for page in range(2, total_pages + 1)
        ]
        async for response in SCRAPFLY.concurrent_scrape(to_scrape):
            results.extend(parse_search(response)["results"])

    return results
```



`scrape_category()` takes the same shape but starts from a category URL instead of a search query, for example `scrape_category(url="https://us.rs-online.com/connectors/d-sub-connectors-contacts-accessories/d-sub-connectors/", max_pages=2)`. For the maintained module, keep the US storefront and `country="us"`, collect product links, paginate, and hand them to the detail scraper below. Other storefronts need their own tested parser and configuration.



## How to Scrape RS-Online Product Detail Pages

North American RS product detail pages carry the richest record for a part, which is the surface BOM, price-monitoring, and component-search tools care about most.

The URL shape is region-dependent. The EU and Asia `/web/` sites use `/web/p/{slug}/{stock-no}`, while the North American Magento site uses `/product/<brand-slug>/<mpn>/<id>/`, for example `/product/cinch/dah15s/70152743/`.

### Extracting price, stock, and the RS Stock Number

The detail page holds the core commercial fields for a single part: the RS Stock No., the MPN, the manufacturer or brand, the price in the storefront currency, availability and stock quantity, minimum order quantity (MOQ), the quantity increment, and tiered pricing breaks where RS publishes them. There is no parsed lead-time duration on the page. What the scraper actually reads is a boolean `lead_time_required` flag off RS's own GA4 tracking data, so treat "lead time" as a flag rather than a duration string.

Price and currency are region-specific, so a USD value from us.rs-online.com does not carry over to uk.rs-online.com/web/.

On the North American site the data delivery is friendly. PDPs are server-rendered with a JSON-LD `Product`/`Offer` block plus a GA4 `dataLayer` variable (`dl4Objects`) carrying the item id, price, category, and the lead-time flag, so `render_js` is not needed for the PDP. The `rs-online-scraper` module pulls both sources:

python```python
def _extract_product_json_ld(sel) -> Dict:
    for script in sel.css('script[type="application/ld+json"]'):
        data = json.loads(script.css("::text").get() or "{}")
        if data.get("@type") == "Product":
            return data
    return {}


def _extract_ga4_item(html: str) -> Dict:
    match = re.search(r"var dl4Objects\s*=\s*(\[.*?\]);\s*\n\s*for", html, re.S)
    if not match:
        return {}
    dl4_objects = json.loads(match.group(1))
    for obj in dl4_objects:
        items = obj.get("ecommerce", {}).get("items", [])
        if items:
            return items[0]
    return {}
```



`parse_product()` combines both with a few DOM reads for the fields neither JSON blob carries, like the RS Stock No., stock quantity, and MOQ:

python```python
product_ld = _extract_product_json_ld(sel)
offers = product_ld.get("offers", {}) or {}
ga4_item = _extract_ga4_item(html)

rs_stock_number = (sel.css(".product.attribute.sku .value::text").get() or "").strip()
mpn = "".join(sel.css('[itemprop="manufacturer_part_number"]::text').getall()).strip()

stock_text = (sel.css(".badge-block.stock-status-bg .badge-text::text").get() or "").strip()
stock_match = re.match(r"(.+?)\s*-\s*(\d+)\s*$", stock_text)
stock_quantity = int(stock_match.group(2)) if stock_match else None

min_order_match = re.search(r'"minSaleQty":\s*(\d+)', html)
qty_increment_match = re.search(r'"qtyIncrements":\s*(\d+)', html)

price = str(offers.get("price")) if offers.get("price") is not None else None
currency = offers.get("priceCurrency") or None
min_order_qty = int(min_order_match.group(1)) if min_order_match else None
qty_increment = int(qty_increment_match.group(1)) if qty_increment_match else None
lead_time_required = (ga4_item.get("request_lead_time") == "Y") if ga4_item else None
```



The normalized record includes the RS Stock No., MPN, price, currency, availability, stock quantity, minimum order quantity, and a boolean lead-time flag.

### Extracting datasheets, specs, and compliance data

The same page carries the technical record: the parametric spec key/value table, the datasheet PDF URL, compliance flags like RoHS, the category, and the product image. None of that is in the JSON-LD or GA4 blob, so the module reads it straight off the DOM:

python```python
specifications = {}
for td in sel.css("td.col.data"):
    label = td.attrib.get("data-th")
    value = (td.css("::text").get() or "").strip()
    if label and value:
        specifications[label] = value

compliance = [text.strip() for text in sel.css(".compliant-block span::text").getall() if text.strip()]
category = ga4_item.get("item_category3") or ga4_item.get("item_category2") or ga4_item.get("item_category")
datasheet_url = sel.css(".downloads-item a::attr(href)").get()
```



Treat the datasheet URL as optional rather than guaranteed. If the selector finds no link, the schema should retain `None` instead of failing the record. The remaining DOM fields populate the specifications dictionary and compliance list when present.

Once you have a clean per-part record, the next job is reconciling it against the other distributors.



## How Do You Normalize RS, Mouser, and DigiKey Records?

A multi-distributor pipeline needs a shared schema before it can compare price or availability. Preserve each source's original identifier and URL, and match records on a normalized `(manufacturer, MPN)` key rather than MPN alone.

python```python
from dataclasses import asdict, dataclass
from typing import Optional


@dataclass
class DistributorPart:
    manufacturer: Optional[str]
    mpn: Optional[str]
    source_id: Optional[str]  # RS Stock No. or the source's equivalent identifier
    distributor: str
    region: str
    price: Optional[str]
    currency: Optional[str]
    stock_quantity: Optional[int]
    availability: Optional[str]
    lead_time_required: Optional[bool]
    min_order_qty: Optional[int]
    datasheet_url: Optional[str]
    source_url: str
    fetched_at: str


def index_by_part(parts: list[DistributorPart]) -> dict:
    """Group records by normalized manufacturer and MPN."""
    index = {}
    for part in parts:
        if not part.manufacturer or not part.mpn:
            continue
        key = (part.manufacturer.strip().casefold(), part.mpn.strip().casefold())
        index.setdefault(key, []).append(asdict(part))
    return index
```



This schema keeps the RS parser's field names and types, including string prices and the boolean `lead_time_required` flag. Before calculating price differences, convert values with `Decimal`, normalize quantity tiers, and apply a timestamped exchange rate. Do not compare a single-unit USD price directly with a volume-tier EUR price.

Run one pass per supported distributor and storefront, then normalize the records. The current RS module supports the North American storefront; add regional RS records only after their parsers and fixtures have been implemented and tested.

For the Mouser side, the guide covers its source-specific extraction. Keep normalization separate from each scraper so selector changes do not leak into comparison logic.



## Scraping the North American Storefront with Scrapfly

ScrapFly's [Web Scraping API](https://scrapfly.io/products/web-scraping-api) is a single endpoint for retrieving web content without maintaining browser and proxy infrastructure yourself.

- [Anti-Scraping Protection](https://scrapfly.io/docs/scrape-api/anti-scraping-protection) handles supported anti-bot challenges; results still depend on the target and configuration.
- [Proxy routing](https://scrapfly.io/docs/scrape-api/proxy) supports country and ASN-level geo-targeting.
- [JavaScript rendering](https://scrapfly.io/docs/scrape-api/javascript-rendering) runs dynamic pages in a cloud browser when the target content requires it.
- [Browser automation scenarios](https://scrapfly.io/docs/scrape-api/javascript-scenario) can scroll, click, fill forms, and wait for elements.
- [Format conversion](https://scrapfly.io/docs/scrape-api/getting-started#api_param_format) can return HTML, JSON, text, or Markdown.
- [Session management](https://scrapfly.io/docs/scrape-api/session) keeps cookies, headers, and IPs consistent across related requests.
- [Caching](https://scrapfly.io/docs/scrape-api/getting-started#api_param_cache) can reduce repeat requests for scheduled snapshots.
- SDKs are available for [Python](https://scrapfly.io/docs/sdk/python), [TypeScript](https://scrapfly.io/docs/sdk/typescript), and [Scrapy](https://scrapfly.io/docs/sdk/scrapy), with additional [integrations](https://scrapfly.io/docs/integration/getting-started).

The maintained RS module uses the following shared configuration for the North American storefront. A standalone request with the same settings looks like this:

python```python
import os

from scrapfly import ScrapflyClient, ScrapeConfig

client = ScrapflyClient(key=os.environ["SCRAPFLY_KEY"])

BASE_CONFIG = {
    "asp": True,
    "country": "us",
    "proxy_pool": "public_residential_pool",
    "rendering_wait": 5000,
}

result = client.scrape(ScrapeConfig(
    url="https://us.rs-online.com/",
    **BASE_CONFIG,
))
print(result.upstream_status_code)
```



Listing requests add `render_js=True` and `wait_for_selector="[data-testid='pagination']"` because the North American product grid is rendered client-side. Product detail pages use the shared configuration without forcing JavaScript rendering.

This configuration and the article's selectors are scoped to `us.rs-online.com`. Changing `country` does not make them compatible with the EU or Asia `/web/` platform. Those storefronts require their own parser, fixtures, and successful validation.

For general platform capabilities, see the [DataDome](https://scrapfly.io/bypass/datadome) and [Akamai](https://scrapfly.io/bypass/akamai) pages. The product and documentation links above cover the configuration options used by this example.



## FAQ

Does RS-Online have an API for product data?Not a public one. Unlike Mouser and DigiKey, RS has no developer portal or product REST API you can sign up for. It offers account-gated eProcurement integrations (PunchOut via OCI or cXML) for trade customers, so scraping the public site is the practical path.







Is it legal to scrape RS-Online?Public RS product and search pages are accessible without authentication, and hiQ Labs v. LinkedIn (9th Circuit, 2022) held that scraping public data does not violate the CFAA. Do not scrape behind logins or trade pricing, store GDPR-protected personal data, or republish whole datasets. This is not legal advice.







Why do RS-Online prices and stock differ between countries?Because RS runs separate regional storefronts, each can expose different pricing, currency, inventory, and identifiers. The current module returns North American data only. A cross-region comparison needs storefront-specific parsers and should match records on a normalized `(manufacturer, MPN)` key, not RS Stock No.







Why does my RS-Online scraper get blocked or return a challenge page?The maintained North American example uses Scrapfly ASP for the DataDome-protected Magento storefront. Changing the User-Agent alone is not a reliable fix because anti-bot systems can evaluate several request and browser signals. Other regional storefronts require separate access verification and parser coverage.







Can I get datasheets and historical pricing from RS-Online?Datasheet PDF URLs appear on most detail pages, but RS has been inconsistent about exposing them, so treat the link as optional. Historical pricing is not published, since RS returns current prices only. Run regular snapshots yourself to track changes over time.









## Conclusion

The maintained `rs-online-scraper` shows how to collect listings and product details from RS-Online's North American Magento storefront. It extracts identifiers, pricing, availability, stock, specifications, compliance data, and optional datasheet links with an async Scrapfly workflow.

That is the implementation boundary. EU and Asia `/web/` storefronts use different routes and markup, and the current module does not include or demonstrate parsers for them. Geo-targeting can select a storefront, but it cannot replace region-specific extraction and tests.

Use the repository block above for the complete runnable module. For production retrieval, Scrapfly's Web Scraping API provides the ASP, proxy, rendering, session, and caching controls used by the North American example.



Legal Disclaimer and PrecautionsThis tutorial covers popular web scraping techniques for education. Interacting with public servers requires diligence and respect:

- Do not scrape at rates that could damage the website.
- Do not scrape data that's not available publicly.
- Do not store PII of EU citizens protected by GDPR.
- Do not repurpose *entire* public datasets which can be illegal in some countries.

Scrapfly does not offer legal advice but these are good general rules to follow. For more you should consult a lawyer.

 

   [  Add as a preferred source ](https://google.com/preferences/source?q=scrapfly.io) Table of Contents















 

  Table of Contents- [Key Takeaways](#key-takeaways)
- [Why Scrape RS-Online?](#why-scrape-rs-online)
- [Does RS-Online Have a Public API?](#does-rs-online-have-a-public-api)
- [Why Is RS-Online Hard to Scrape?](#why-is-rs-online-hard-to-scrape)
- [How Do RS-Online's Regional Sites and Currencies Differ?](#how-do-rs-online-s-regional-sites-and-currencies-differ)
- [Setting Up the Scraper](#setting-up-the-scraper)
- [How to Scrape RS-Online Search and Category Listings](#how-to-scrape-rs-online-search-and-category-listings)
- [How to Scrape RS-Online Product Detail Pages](#how-to-scrape-rs-online-product-detail-pages)
- [Extracting price, stock, and the RS Stock Number](#extracting-price-stock-and-the-rs-stock-number)
- [Extracting datasheets, specs, and compliance data](#extracting-datasheets-specs-and-compliance-data)
- [How Do You Normalize RS, Mouser, and DigiKey Records?](#how-do-you-normalize-rs-mouser-and-digikey-records)
- [Scraping the North American Storefront with Scrapfly](#scraping-the-north-american-storefront-with-scrapfly)
- [FAQ](#faq)
- [Conclusion](#conclusion)
 
    Join the Newsletter  Get monthly web scraping insights 

 

  



Scale Your Web Scraping

Anti-bot bypass, browser rendering, and rotating proxies, all in one API. Start with 1,000 free credits.

  No credit card required  1,000 free API credits  Anti-bot bypass included 

 [Start Free](https://scrapfly.io/register) [View Docs](https://scrapfly.io/docs/onboarding) 

 Not ready? Get our newsletter instead. 

 

 ## Related Articles

 [  

 python scrapeguide 

### How to Scrape YellowPages.com in 2026

Tutorial on how to scrape yellowpages.com business and review data using Python. How to avoid blocking to scrape data at...

 

 ](https://scrapfly.io/blog/posts/how-to-scrape-yellowpages) [     

 python beautifulsoup 

### How to Scrape Allegro.pl in 2026

Scrape Allegro.pl product listings and detail pages with Scrapfly. Bypass DataDome anti-bot protection. Route through Po...

 

 ](https://scrapfly.io/blog/posts/how-to-scrape-allegro) [  

 python scrapeguide 

### How to Scrape Amazon.com Product Data and Reviews

This scrape guide covers the biggest e-commerce platform in US - Amazon.com. We'll take a look how to scrape product dat...

 

 ](https://scrapfly.io/blog/posts/how-to-scrape-amazon) 

  ## Related Questions

- [ Q How to find all links using BeautifulSoup and Python? ](https://scrapfly.io/blog/answers/how-to-find-all-links-using-beautifulsoup)
 
  



   



 Scale your web scraping effortlessly, **1,000 free credits** [Start Free](https://scrapfly.io/register)