Skip to content
Guides 6 Connection Type: 2 views

Proxy in Scrapy-Splash for JavaScript Page Rendering

Discover how to configure and use GProxy within your Scrapy-Splash projects to render JavaScript-heavy pages and scrape dynamic web content reliably.

Parsing Python

Integrating proxies into Scrapy-Splash allows requests originating from the Splash rendering service to be routed through an intermediary server, enabling IP rotation, geo-unblocking, and anonymity for JavaScript-rendered web pages.

Understanding Proxy Integration with Scrapy-Splash

Scrapy-Splash combines Scrapy's scraping framework with Splash's headless browser rendering capabilities. When a proxy is configured within this setup, it means the web requests made by the browser instance inside Splash are directed through the specified proxy server. This applies to the initial page load, subsequent AJAX requests, and any other network activity initiated by the JavaScript on the page.

Why Use Proxies with Scrapy-Splash?

Proxies serve several critical functions when scraping dynamic content with Scrapy-Splash:
* Bypassing IP-based Rate Limits and Blocks: Websites often restrict access based on the originating IP address. Proxies allow distributing requests across multiple IPs, mitigating such restrictions.
* Accessing Geo-restricted Content: Proxies located in specific geographical regions can access content unavailable in the scraper's physical location.
* Maintaining Anonymity: Proxies obscure the scraper's true IP address, enhancing operational security.
* Distributing Load: For large-scale operations, proxies can help distribute the network load and reduce the chance of a single IP being overwhelmed or flagged.

How Scrapy-Splash Handles Proxy Requests

  1. Scrapy dispatches a SplashRequest to the Splash daemon.
  2. Splash receives the request and, if a proxy argument is present, configures its internal browser instance (e.g., Chromium) to route all network traffic through that proxy.
  3. The browser instance navigates to the target URL, renders the JavaScript, and makes any necessary network calls (e.g., XHRs, fetching assets) via the configured proxy.
  4. Splash returns the fully rendered HTML, screenshot, or other requested data back to Scrapy.

Configuring Proxies in Scrapy-Splash

The primary method for proxy integration is via the proxy argument in SplashRequest.

Basic Proxy Configuration

To use a proxy for a specific request, pass the proxy argument within the args dictionary of SplashRequest. The proxy URL format is [protocol://][user:password@]host:port.

import scrapy
from scrapy_splash import SplashRequest

class BasicProxySpider(scrapy.Spider):
    name = 'basic_proxy_spider'
    start_urls = ['http://quotes.toscrape.com/js/']

    def start_requests(self):
        # Example using a basic HTTP proxy
        # Replace with your actual proxy IP and port
        yield SplashRequest(
            url=self.start_urls[0],
            callback=self.parse,
            args={
                'wait': 0.5,
                'proxy': 'http://your_proxy_ip:port'
            }
        )

    def parse(self, response):
        title = response.css('title::text').get()
        yield {
            'title': title,
            'url': response.url,
            'proxy_used': response.request.meta.get('splash', {}).get('args', {}).get('proxy')
        }

Authenticated Proxies

For proxies requiring authentication, embed the username and password directly into the proxy URL string.

import scrapy
from scrapy_splash import SplashRequest

class AuthenticatedProxySpider(scrapy.Spider):
    name = 'auth_proxy_spider'
    start_urls = ['http://quotes.toscrape.com/js/']

    def start_requests(self):
        # Replace with your actual proxy details
        proxy_user = 'your_username'
        proxy_pass = 'your_password'
        proxy_host = 'your_proxy_ip'
        proxy_port = 'port'

        authenticated_proxy_url = f'http://{proxy_user}:{proxy_pass}@{proxy_host}:{proxy_port}'

        yield SplashRequest(
            url=self.start_urls[0],
            callback=self.parse,
            args={
                'wait': 0.5,
                'proxy': authenticated_proxy_url
            }
        )

    def parse(self, response):
        title = response.css('title::text').get()
        yield {
            'title': title,
            'url': response.url,
            'proxy_used': response.request.meta.get('splash', {}).get('args', {}).get('proxy')
        }

Dynamic Proxy Selection and Rotation

For scenarios requiring different proxies per request or a rotation scheme, manage a list of proxies within your spider and select one dynamically.

import scrapy
from scrapy_splash import SplashRequest
import random

class RotatingProxySpider(scrapy.Spider):
    name = 'rotating_proxy_spider'
    start_urls = ['http://quotes.toscrape.com/js/', 'http://toscrape.com/']

    # Define a list of proxies (replace with your actual proxies)
    # Include authenticated proxies as 'http://user:pass@host:port'
    proxy_list = [
        'http://proxy1_ip:port1',
        'http://user:pass@proxy2_ip:port2',
        'http://proxy3_ip:port3',
    ]

    def start_requests(self):
        for url in self.start_urls:
            selected_proxy = random.choice(self.proxy_list)
            yield SplashRequest(
                url=url,
                callback=self.parse,
                args={
                    'wait': 0.5,
                    'proxy': selected_proxy
                },
                # You can also pass custom meta to track which proxy was used
                meta={'proxy_selected': selected_proxy} 
            )

    def parse(self, response):
        title = response.css('title::text').get()
        yield {
            'title': title,
            'url': response.url,
            'proxy_used': response.request.meta.get('proxy_selected') # Access custom meta
        }

Global Proxy Configuration (Splash Daemon)

Splash can be configured to use a default proxy for all its outbound requests. This is typically achieved by setting HTTP_PROXY and HTTPS_PROXY environment variables before starting the Splash daemon. While this provides a global default, it offers less control than per-request proxy specification for dynamic scraping tasks.

Proxy Types and Their Impact

The choice of proxy type affects anonymity, performance, and detection risk.

Feature Datacenter Proxies Residential Proxies
IP Source Commercial data centers Real residential ISPs
Anonymity Moderate (IPs often belong to known subnets) High (IPs appear as regular consumer internet users)
Speed Generally faster due to dedicated infrastructure Can be slower due to routing through residential networks
Cost Lower per IP Higher per IP or bandwidth
Detection More prone to detection and blocking by sophisticated anti-bots Less prone to detection; harder to block
Use Cases General scraping, high-volume tasks on less protected sites Highly sensitive scraping, bypassing advanced anti-bot systems

Proxy Protocols

  • HTTP/HTTPS Proxies: Handle standard web traffic. Splash fully supports both protocols.
  • SOCKS Proxies: SOCKS (SOCKS4, SOCKS5) proxies operate at a lower level, capable of handling various network protocols, not just HTTP/HTTPS. To use a SOCKS proxy with Splash, specify the protocol in the proxy URL (e.g., socks5://user:pass@host:port).

Sticky vs. Rotating Proxies

  • Sticky Proxies: Maintain the same IP address for a defined duration (e.g., a few minutes to hours) or for the lifetime of a session. Useful for maintaining session state on target websites that require consistent IP addresses.
  • Rotating Proxies: Assign a new IP address with each request or at regular, short intervals. Ideal for high-volume scraping where avoiding IP bans by frequently changing the origin IP is critical.

Troubleshooting and Best Practices

Verify Proxy Connectivity

Before large-scale deployment, test your proxy independently. A simple curl command or a Python requests script can confirm the proxy's functionality and accessibility.

curl --proxy http://your_proxy_ip:port http://httpbin.org/ip

Check Splash Logs

Issues related to proxy connectivity or authentication within Splash are typically logged by the Splash daemon. Review Splash's console output or log files for errors when debugging.

Handle Proxy Errors Gracefully

Implement retry mechanisms or proxy rotation logic to handle failed requests. If a proxy consistently fails, remove it from the active pool or mark it as unhealthy for a period. Scrapy's retry middleware can be adapted, but proxy-specific failure handling often requires custom spider logic.

Performance Considerations

Proxies introduce an additional network hop, increasing latency.
* Proxy Pool Management: Implement a system to track proxy health, response times, and usage. Prioritize faster, reliable proxies.
* Resource Usage: Splash itself is resource-intensive. Using proxies adds overhead. Ensure the Splash daemon has adequate CPU and RAM to handle the combined load.

Website-Specific Anti-Bot Measures

Advanced anti-bot systems detect patterns beyond simple IP addresses. Even with residential proxies, sites might identify automated browsing. Fine-tune Splash arguments such as user-agent, viewport, browser_params, and use custom Lua scripts for more human-like interactions to counter these measures.

IP Leakage

Confirm that the proxy effectively masks the scraper's true IP. Use services like http://httpbin.org/ip or https://ipleak.net/ within Splash to verify the visible IP address.

# Lua script to check the visible IP within Splash
lua_script = """
function main(splash)
    splash:set_proxy_auto() -- Ensures proxy is used if set via 'proxy' argument
    splash:go("http://httpbin.org/ip")
    splash:wait(0.5)
    return splash:html()
end
"""

# Example SplashRequest using the Lua script
yield SplashRequest(
    url="about:blank", # URL here does not matter as Lua handles navigation
    callback=self.parse_ip_check,
    endpoint='execute',
    args={
        'lua_source': lua_script,
        'proxy': 'http://your_proxy_ip:port',
        'timeout': 90 # Increase timeout for Lua scripts
    }
)

def parse_ip_check(self, response):
    # Parse the HTML response from httpbin.org/ip to extract the IP
    ip_address = response.css('pre::text').get() # Adjust selector if httpbin changes
    self.logger.info(f"Visible IP from Splash via proxy: {ip_address}")
    # Further processing...
Auto-update: 04.03.2026
All Categories

Advantages of our proxies

25,000+ proxies from 120+ countries