{"id":9418,"library":"zenrows","title":"ZenRows Python SDK","description":"ZenRows is a Python client for the ZenRows API, designed to simplify web scraping by automatically handling challenges like proxy rotation, CAPTCHA solving, and JavaScript rendering. It enables users to extract data from complex, anti-bot protected websites. The library is actively maintained, currently at version 1.4.0, with regular updates to its API and SDKs.","status":"active","version":"1.4.0","language":"en","source_language":"en","source_url":"https://github.com/ZenRows/zenrows-python-sdk","tags":["web scraping","proxy","anti-bot","headless browser","api client","scraping","data extraction"],"install":[{"cmd":"pip install zenrows","lang":"bash","label":"Install ZenRows SDK"}],"dependencies":[{"reason":"Used internally by the SDK for HTTP requests and often directly by users for integration with other scraping tools.","package":"requests","optional":false},{"reason":"Handles connection pooling and retries; a dependency of requests.","package":"urllib3","optional":false},{"reason":"Used for concurrent (asynchronous) requests.","package":"asyncio","optional":true}],"imports":[{"note":"The primary interaction is through the 'ZenRowsClient' class, not the top-level 'zenrows' module directly.","wrong":"import zenrows","symbol":"ZenRowsClient","correct":"from zenrows import ZenRowsClient"}],"quickstart":{"code":"import os\nfrom zenrows import ZenRowsClient\n\n# Get your API key from environment variable for security\nZENROWS_API_KEY = os.environ.get('ZENROWS_API_KEY', 'YOUR_ZENROWS_API_KEY')\n\nif not ZENROWS_API_KEY or ZENROWS_API_KEY == 'YOUR_ZENROWS_API_KEY':\n    print(\"Warning: ZENROWS_API_KEY environment variable not set or is default. Please replace with your actual API key.\")\n    # Exit or raise error in production code\n\nclient = ZenRowsClient(ZENROWS_API_KEY)\n\n# Make a GET request to a target URL with JavaScript rendering enabled\ntarget_url = 'https://www.example.com'\nresponse = client.get(target_url, params={'js_render': 'true', 'premium_proxy': 'true'})\n\nif response.status_code == 200:\n    print(f\"Successfully scraped {target_url}. Partial content:\\n{response.text[:500]}...\")\nelse:\n    print(f\"Failed to scrape {target_url}. Status code: {response.status_code}, Error: {response.text}\")\n","lang":"python","description":"This quickstart demonstrates how to initialize the ZenRows client with an API key (preferably from an environment variable) and make a basic GET request to a target URL, enabling common features like JavaScript rendering and premium proxies. The response object is a standard `requests.Response` object."},"warnings":[{"fix":"Initialize client with `client = ZenRowsClient('YOUR-API-KEY', retries=3)`.","message":"Retries are not active by default. You must explicitly specify the `retries` parameter when initializing `ZenRowsClient` if you want automatic retries for failed requests (e.g., 429, 5xx errors).","severity":"gotcha","affected_versions":"All versions"},{"fix":"Wrap async calls in an `async def main():` and execute with `asyncio.run(main())`.","message":"When performing asynchronous requests, ensure you use `client.get_async` (or `post_async`, etc.) and run your async function with `asyncio.run()`, otherwise, coroutine errors will occur.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Be cautious with custom headers; only send them if necessary and test thoroughly. Contact ZenRows support if issues arise.","message":"Sending custom headers to the target URL might overwrite ZenRows' default headers, potentially leading to increased detection or blocking.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Pass a dictionary of CSS selectors to the `css_extractor` parameter: `params={'css_extractor': {'title': 'h1', 'links': 'a @href'}}`.","message":"Using the `css_extractor` parameter is often more efficient than fetching the entire HTML and then parsing it with libraries like BeautifulSoup, especially for large responses or limited bandwidth.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Always store your API key securely, preferably in an environment variable (`ZENROWS_API_KEY`) and load it at runtime.","message":"The ZenRows API key is essential for authentication and usage tracking. Exposing it directly in code or public repositories is a security risk.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-16T00:00:00.000Z","next_check":"2026-07-15T00:00:00.000Z","problems":[{"fix":"If using `async` methods, define an `async def main():` function containing your async calls and run it with `asyncio.run(main())`.","cause":"Attempting to call an asynchronous method (e.g., `client.get_async`) without properly awaiting it or running it within an `asyncio` event loop.","error":"coroutine 'main' was never awaited"},{"fix":"Implement retry logic with exponential backoff (using the `retries` parameter) or reduce your concurrency. Check your ZenRows dashboard for plan limits.","cause":"You have exceeded your account's concurrent request limit or rate limit.","error":"HTTP Error 429: Too Many Requests"},{"fix":"Enable `js_render: true`, `premium_proxy: true`, or add a `referer` header. You might also need to use `wait_for` or `wait` parameters for dynamically loaded content.","cause":"The anti-bot protection on the target website is blocking your request. This often indicates ZenRows couldn't bypass the protection with the current parameters.","error":"HTTP Error 422: Unprocessable Entity"},{"fix":"Verify your ZenRows API key and proxy credentials from your dashboard. Ensure the proxy URL format is `http://username:password@proxy-host:port` and the protocol/port match (e.g., 1337 for HTTP, 1338 for HTTPS).","cause":"Using an incorrect API key, username, password, or proxy host/port when configuring proxies directly (not using the SDK client).","error":"Incorrect Credentials / Connection Refused (when using direct proxy setup)"}]}