{"id":2215,"library":"pycurl","title":"PycURL - A Python Interface To The cURL library","description":"PycURL is a Python interface to the `libcurl` library, providing fast and feature-rich capabilities for network operations. It supports numerous protocols including HTTP, HTTPS, FTP, and more, exposing most of `libcurl`'s functionality like SSL, authentication, and proxy options. PycURL is often chosen for performance-critical applications and I/O multiplexing due to its speed. The current version is 7.45.7, with releases occurring periodically to incorporate `libcurl` updates and security fixes.","status":"active","version":"7.45.7","language":"en","source_language":"en","source_url":"https://github.com/pycurl/pycurl","tags":["http","https","curl","libcurl","network","transfer","ftp","ssl","performance","multiprotocol"],"install":[{"cmd":"pip install pycurl","lang":"bash","label":"Install PycURL via pip"},{"cmd":"sudo apt-get install libcurl4-openssl-dev python3-pycurl","lang":"bash","label":"Debian/Ubuntu (including libcurl-dev)"},{"cmd":"brew install curl","lang":"bash","label":"macOS (Homebrew, then pip install)"}],"dependencies":[{"reason":"PycURL is a C extension that wraps the system's libcurl library. Its development headers are often required for successful installation, especially from source.","package":"libcurl"},{"reason":"Recommended for managing SSL certificate bundles, especially when performing HTTPS requests.","package":"certifi","optional":true}],"imports":[{"symbol":"pycurl","correct":"import pycurl"},{"symbol":"Curl","correct":"import pycurl\nc = pycurl.Curl()"},{"note":"Commonly used with pycurl.WRITEDATA to capture response body in memory.","symbol":"BytesIO","correct":"from io import BytesIO"}],"quickstart":{"code":"import pycurl\nfrom io import BytesIO\n\ndef fetch_url(url):\n    buffer = BytesIO()\n    c = pycurl.Curl()\n    c.setopt(c.URL, url)\n    c.setopt(c.WRITEDATA, buffer)\n    # Optional: For HTTPS, use certifi for certificate bundle\n    # import certifi\n    # c.setopt(c.CAINFO, certifi.where())\n    \n    try:\n        c.perform()\n        status_code = c.getinfo(pycurl.RESPONSE_CODE)\n        response_body = buffer.getvalue().decode('utf-8', errors='ignore')\n        print(f\"Status Code: {status_code}\")\n        print(f\"Response Body (first 200 chars):\\n{response_body[:200]}\")\n    except pycurl.error as e:\n        print(f\"PycURL error: {e}\")\n    finally:\n        c.close()\n\n# Example usage\nfetch_url('https://httpbin.org/get')","lang":"python","description":"This quickstart demonstrates how to perform a basic GET request using PycURL. It initializes a Curl object, sets the URL, and uses `io.BytesIO` to capture the response body. Error handling for PycURL specific errors is included. It also highlights an optional step for using `certifi` for robust HTTPS certificate verification."},"warnings":[{"fix":"Ensure `libcurl` and its development packages are installed on your system before `pip install pycurl`.","message":"PycURL is a wrapper around `libcurl`, a system library. Installing PycURL via pip often requires `libcurl` and its development headers (e.g., `libcurl4-openssl-dev` on Debian/Ubuntu, `curl` on macOS via Homebrew) to be present on your system. Without these, installation may fail or lead to runtime errors, especially when building from source.","severity":"gotcha","affected_versions":"All versions"},{"fix":"During installation, explicitly tell `setup.py` which SSL backend to use via the `PYCURL_SSL_LIBRARY` environment variable (e.g., `export PYCURL_SSL_LIBRARY=openssl pip install pycurl`) or `setup.py` command-line options.","message":"SSL backend mismatches can cause runtime `ImportError` (e.g., `pycurl: libcurl link-time ssl backend (...) is different from compile-time ssl backend (...)`). This occurs if PycURL is built against a different SSL library than what `libcurl` uses at runtime.","severity":"gotcha","affected_versions":"All versions, particularly on custom builds or environments with multiple SSL libraries."},{"fix":"Always decode received `bytes` to `str` for text, and encode `str` to `bytes` when sending non-ASCII data to PycURL. Use `errors='ignore'` or `errors='replace'` during decoding if dealing with unknown/malformed encodings.","message":"PycURL returns all network data as `bytes` objects. For text content, you must explicitly decode these `bytes` to `str` (e.g., using `.decode('utf-8')`). Conversely, when passing non-ASCII Unicode strings to `setopt` or `READFUNCTION`, they must first be encoded into `bytes` to avoid `UnicodeEncodeError` or `pycurl.error` (e.g., 'read function error/data error').","severity":"gotcha","affected_versions":"Python 3.x"},{"fix":"Prefer `c.setopt(c.WRITEDATA, buffer)` over `WRITEFUNCTION` when providing a simple writeable object to capture response data.","message":"While `c.setopt(c.WRITEFUNCTION, buffer.write)` still works, as of PycURL 7.19.3, `c.setopt(c.WRITEDATA, buffer)` is generally preferred and simpler as it accepts any Python object with a `write` method (like `io.BytesIO`).","severity":"deprecated","affected_versions":"PycURL 7.19.3+"},{"fix":"Update `DEBUGFUNCTION` implementations on Python 3 to handle `bytes` arguments.","message":"The `DEBUGFUNCTION` callback on Python 3 now expects its argument to be `bytes` instead of a (Unicode) `string`.","severity":"breaking","affected_versions":"PycURL 7.19.5.2 and later (on Python 3)"},{"fix":"Access `CURLMOPT_*` constants either directly from the `pycurl` module (e.g., `pycurl.CURLMOPT_PIPELINING`) or from a `CurlMulti` instance (e.g., `multi_handle.CURLMOPT_PIPELINING`).","message":"The `CURLMOPT_*` option constants, related to the multi interface, were moved from the `Easy` class to the `Multi` class. They remain available in the top-level `pycurl` module for backward compatibility.","severity":"breaking","affected_versions":"PycURL 7.19.5.2 and later"}],"env_vars":null,"last_verified":"2026-04-09T00:00:00.000Z","next_check":"2026-07-08T00:00:00.000Z"}