faster-than-requests is a free, open source data extraction & web scraping project written in Nim and released under MIT. It has 1,128 GitHub stars, 89 forks and 0 open issues, and was last pushed 11 days ago. On this registry it ranks #78 of 105 tracked projects in Data Extraction & Web Scraping, with 5 head-to-head comparisons available.

What is faster-than-requests?

faster-than-requests is an MIT-licensed Python 3 HTTP client written in Nim that keeps a requests-style call surface while adding a built-in multi-threaded web scraper, shipping as a single file with no direct dependencies, and it is aimed at developers doing high-volume scraping or downloads who find python-requests, urllib3, or PyCURL too slow.

What it is

faster-than-requests is a Python 3 library imported as "faster_than_requests" and conventionally aliased: import faster_than_requests as requests. The public surface deliberately mirrors python-requests, so familiar verbs such as get(), post(), put(), head(), patch(), and delete() carry over, alongside response helpers get2str(), get2dict(), get2json(), post2str(), post2dict(), and post2json(). The implementation is a Nim library, distributed as one file of 999 lines of code with zero direct dependencies, and it is released under the MIT licence. Beyond plain HTTP, it exposes file download helpers download() and download2(), a WebSocket client through websocket_send(), and seven scraper entry points, scraper() through scraper7().

The concrete problem it solves is throughput in Python data extraction and web scraping, where the request library itself becomes the bottleneck. The README's own comparison table measures the real time needed to complete 10,000 local HTTP requests, and reports faster_than_requests at 0.40 against Requests at 15.58, a cached Requests object at 5.50, urllib at 4.00, urllib3 at 3.55, PyCURL at 0.75, and PyWGET at 152.39. It therefore replaces python-requests and urllib3 as the transport layer, and it also absorbs work that would otherwise be handed to Scrapy or a hand-rolled thread pool, since multi-threaded crawling and extraction are built in.

Key capabilities

  • Standard HTTP verbs get(), post(), put(), head(), patch(), and delete() for direct call-for-call replacement of python-requests code.
  • File download through download() and download2(), for example requests.download("http://example.com/foo.jpg", "out.jpg").
  • Multi-threaded web scraping via scraper(), invoked as requests.scraper(["http://foo.io", "http://bar.io"], threads=True), with a one-liner example at examples/multithread_web_scraper.py.
  • URL-to-SQLite scraping through scraper5(), which takes sqlite_file_path="database.db" and writes crawled URLs into a database.
  • Regex-powered scraping through scraper6(), for example requests.scraper6(["http://python.org"], ["(www|http:|https:)+[^\s]+[\w]"]).
  • CSS-selector scraping through scraper7(), for example requests.scraper7("http://python.org", "body > div.someclass a#someid").
  • WebSockets for binary and text frames over websocket_send(), for example requests.websocket_send("ws://echo.websocket.org", "data here").

Who uses it and how

  • Scraping pipelines that fan out across many URLs use scraper() with threads=True instead of maintaining their own worker pool.
  • Teams that need crawled results persisted rather than printed point scraper5() at a sqlite_file_path and land results directly in a SQLite database.
  • Scrapers targeting specific DOM nodes use scraper7() with a CSS selector instead of parsing HTML downstream.
  • Harvesting links or patterns from open-data pages uses scraper6() with a regular expression such as (www|http:|https:)+[^\s]+[\w].
  • Asset-heavy jobs, such as bulk image or file retrieval, use download() and download2() rather than looping over get() calls.

Getting started

The README's "Use" section shows the whole entry point: import faster_than_requests as requests, then call requests.get("http://httpbin.org/get") or any of the other functions directly. No package manager command, Docker image, or compose file appears in the provided material, so the import line is the documented starting point; the repository homepage is a GitHub gist.

How it compares

Within the readme's own benchmark table, faster_than_requests is positioned against python-requests, a cached Requests object, urllib, urllib3, PyCURL, and PyWGET on raw elapsed time for 10,000 local requests, and it is the only entry in that table marked as having WebSockets and a built-in multi-threaded scraper. Its topics also place it alongside requests-toolbelt, requests3, and Scrapy in the same problem space, though the facts describe no paid product that it replaces.

When to use it — and when not to

The appeal for a self-hoster is operational: one file, zero direct dependencies, and no database, storage, or SMTP service to run, although scraper5() does require a writable SQLite database path. It is a poor fit for teams that depend on the surrounding python-requests ecosystem, such as session adapters, authentication helpers, or requests-toolbelt extensions, since those are not documented here. The honest caveat is that the benchmark figures carry the README's own footnote, "Stats as of year 2020," measured on one x86_64 64-bit AMD machine with an SSD running Arch Linux via Docker, and the contributor count for the package is one, so the speed advantage should be re-measured on the target workload.

project readme (upstream, from github) — read inline

Faster-than-Requests

screenshot

screenshot

Library Speed Files LOC Dependencies Developers WebSockets Multi-Threaded Web Scraper Built-in
PyWGET 152.39 1 338 Wget >17 :negative_squared_cross_mark: :negative_squared_cross_mark:
Requests 15.58 >20 2558 >=7 >527 :negative_squared_cross_mark: :negative_squared_cross_mark:
Requests (cached object) 5.50 >20 2558 >=7 >527 :negative_squared_cross_mark: :negative_squared_cross_mark:
Urllib 4.00 ??? 1200 0 (std lib) ??? :negative_squared_cross_mark: :negative_squared_cross_mark:
Urllib3 3.55 >40 5242 0 (No SSL), >=5 (SSL) >188 :negative_squared_cross_mark: :negative_squared_cross_mark:
PyCurl 0.75 >15 5932 Curl, LibCurl >50 :negative_squared_cross_mark: :negative_squared_cross_mark:
PyCurl (no SSL) 0.68 >15 5932 Curl, LibCurl >50 :negative_squared_cross_mark: :negative_squared_cross_mark:
Faster_than_requests 0.40 1 999 0 1 :heavy_check_mark: :heavy_check_mark: 7, One-Liner
  • Lines Of Code counted using CLOC.
  • Direct dependencies of the package when ready to run.
  • Benchmarks run on Docker from Dockerfile on this repo.
  • Developers counted from the Contributors list of Git.
  • Speed is IRL time to complete 10000 HTTP local requests.
  • Stats as of year 2020.
  • x86_64 64Bit AMD, SSD, Arch Linux.

Use

import faster_than_requests as requests

requests.get("http://httpbin.org/get")                                      # GET
requests.post("http://httpbin.org/post", "Some Data Here")                  # POST
requests.download("http://example.com/foo.jpg", "out.jpg")                  # Download a file
requests.scraper(["http://foo.io", "http://bar.io"], threads=True)          # Multi-Threaded Web Scraper
requests.scraper5(["http://foo.io"], sqlite_file_path="database.db")        # URL-to-SQLite Web Scraper
requests.scraper6(["http://python.org"], ["(www|http:|https:)+[^\s]+[\w]"]) # Regex-powered Web Scraper
requests.scraper7("http://python.org", "body > div.someclass a#someid"])    # CSS Selector Web Scraper
requests.websocket_send("ws://echo.websocket.org", "data here")             # WebSockets Binary/Text

Table Of Contents

get()

Description: Takes an URL string, makes an HTTP GET and returns a dict with the response.

Arguments:

  • url the remote URL, string type, required, must not be empty string, example https://dev.to.
  • user_agent User Agent, string type, optional, should not be empty string.
  • max_redirects Maximum Redirects, int type, optional, defaults to 9, example 5, example 1.
  • proxy_url Proxy URL, string type, optional, if is "" then NO Proxy is used, defaults to "", example 172.15.256.1:666.
  • proxy_auth Proxy Auth, string type, optional, if proxy_url is "" then is ignored, defaults to "".
  • timeout Timeout, int type, optional, Milliseconds precision, defaults to -1, example 9999, example 666.
  • http_headers HTTP Headers, List of Tuples type, optional, example [("key", "value")], example [("DNT", "1")].

Examples:

import faster_than_requests as requests
requests.get("http://example.com")

Returns: Response, list type, values of the list are string type, values of the list can be empty string, the lenght of the list is always 7 items, the values are like [body, type, status, version, url, length, headers], you can use to_json() to get JSON or to_dict() to get a dict or to_tuples() to get a tuples.

See Also: get2str() and get2str2()

post()

Description: Takes an URL string, makes an HTTP POST and returns a dict with the response.

Arguments:

  • url the remote URL, string type, required, must not be empty string, example https://dev.to.
  • body the Body data, string type, required, can be empty string. To Post Files use this too.
  • multipart_data MultiPart data, optional, list of tupes type, must not be empty list, example [("key", "value")].
  • user_agent User Agent, string type, optional, should not be empty string.
  • max_redirects Maximum Redirects, int type, optional, defaults to 9, example 5, example 1.
  • proxy_url Proxy URL, string type, optional, if is "" then NO Proxy is used, defaults to "", example 172.15.256.1:666.
  • proxy_auth Proxy Auth, string type, optional, if proxy_url is "" then is ignored, defaults to "".
  • `

readme truncated — read the full docs on github

Frequently asked questions

Is faster-than-requests free to use?

faster-than-requests is open source under the MIT licence. There is no licence fee and no seat count — you can self-host it or, where the project offers one, pay a vendor for a managed version instead.

What does faster-than-requests do?

Faster requests on Python 3

What is faster-than-requests written in?

faster-than-requests is primarily written in Nim. Its source is publicly available at https://github.com/juancarlospaco/faster-than-requests, and it has 1,128 GitHub stars.