|
| 1 | +--- |
| 2 | +id: request-loaders |
| 3 | +title: Request loaders |
| 4 | +description: How to manage the requests your crawler will go through. |
| 5 | +--- |
| 6 | + |
| 7 | +import ApiLink from '@site/src/components/ApiLink'; |
| 8 | + |
| 9 | +import Tabs from '@theme/Tabs'; |
| 10 | +import TabItem from '@theme/TabItem'; |
| 11 | +import CodeBlock from '@theme/CodeBlock'; |
| 12 | + |
| 13 | +import RlBasicSource from '!!raw-loader!./request_loaders_rl_basic.ts'; |
| 14 | +import SitemapBasicSource from '!!raw-loader!./request_loaders_sitemap_basic.ts'; |
| 15 | +import RlTandemExplicitSource from '!!raw-loader!./request_loaders_rl_tandem_explicit.ts'; |
| 16 | +import RlTandemHelperSource from '!!raw-loader!./request_loaders_rl_tandem_helper.ts'; |
| 17 | +import SitemapTandemExplicitSource from '!!raw-loader!./request_loaders_sitemap_tandem_explicit.ts'; |
| 18 | +import SitemapTandemHelperSource from '!!raw-loader!./request_loaders_sitemap_tandem_helper.ts'; |
| 19 | + |
| 20 | +Request loaders extend the functionality of the <ApiLink to="core/class/RequestQueue">`RequestQueue`</ApiLink>, providing additional tools for managing URLs and requests. If you are new to Crawlee and unfamiliar with the <ApiLink to="core/class/RequestQueue">`RequestQueue`</ApiLink>, consider starting with the [Request storage](./request-storage) guide first. Request loaders define how requests are fetched and stored, enabling various use cases such as reading URLs from a static list, a sitemap, an external API, or combining multiple sources together. |
| 21 | + |
| 22 | +## Overview |
| 23 | + |
| 24 | +The request loader abstractions are built around two interfaces and a couple of helpers: |
| 25 | + |
| 26 | +- <ApiLink to="core/interface/IRequestLoader">`IRequestLoader`</ApiLink>: The base interface for reading requests in a crawl. |
| 27 | +- <ApiLink to="core/interface/IRequestManager">`IRequestManager`</ApiLink>: Extends `IRequestLoader` with write capabilities (adding and reclaiming requests). |
| 28 | +- <ApiLink to="core/class/RequestManagerTandem">`RequestManagerTandem`</ApiLink>: Combines a read-only `IRequestLoader` with a writable `IRequestManager`. |
| 29 | + |
| 30 | +And the concrete request loader implementations: |
| 31 | + |
| 32 | +- <ApiLink to="core/class/RequestList">`RequestList`</ApiLink>: A lightweight implementation for managing a static list of URLs. |
| 33 | +- <ApiLink to="core/class/SitemapRequestLoader">`SitemapRequestLoader`</ApiLink>: A specialized loader that reads URLs from XML and plain-text sitemaps following the [Sitemaps protocol](https://www.sitemaps.org/protocol.html), with filtering capabilities. |
| 34 | + |
| 35 | +Below is a class diagram that illustrates the relationships between these components and the <ApiLink to="core/class/RequestQueue">`RequestQueue`</ApiLink>: |
| 36 | + |
| 37 | +```mermaid |
| 38 | +--- |
| 39 | +config: |
| 40 | + class: |
| 41 | + hideEmptyMembersBox: true |
| 42 | +--- |
| 43 | +
|
| 44 | +classDiagram |
| 45 | +
|
| 46 | +%% ======================== |
| 47 | +%% Abstract interfaces |
| 48 | +%% ======================== |
| 49 | +
|
| 50 | +class IRequestLoader { |
| 51 | + <<interface>> |
| 52 | + + getTotalCount() |
| 53 | + + getPendingCount() |
| 54 | + + getHandledCount() |
| 55 | + + fetchNextRequest() |
| 56 | + + markRequestHandled() |
| 57 | + + isEmpty() |
| 58 | + + isFinished() |
| 59 | + + toTandem() |
| 60 | +} |
| 61 | +
|
| 62 | +class IRequestManager { |
| 63 | + <<interface>> |
| 64 | + + addRequest() |
| 65 | + + addRequestsBatched() |
| 66 | + + reclaimRequest() |
| 67 | + + purge() |
| 68 | +} |
| 69 | +
|
| 70 | +%% ======================== |
| 71 | +%% Concrete classes |
| 72 | +%% ======================== |
| 73 | +
|
| 74 | +class RequestQueue |
| 75 | +
|
| 76 | +class RequestList |
| 77 | +
|
| 78 | +class SitemapRequestLoader |
| 79 | +
|
| 80 | +class RequestManagerTandem |
| 81 | +
|
| 82 | +%% ======================== |
| 83 | +%% Inheritance arrows |
| 84 | +%% ======================== |
| 85 | +
|
| 86 | +IRequestLoader <|-- IRequestManager |
| 87 | +IRequestLoader <|.. RequestList |
| 88 | +IRequestLoader <|.. SitemapRequestLoader |
| 89 | +IRequestManager <|.. RequestQueue |
| 90 | +IRequestManager <|.. RequestManagerTandem |
| 91 | +``` |
| 92 | + |
| 93 | +:::info Crawler usage |
| 94 | + |
| 95 | +A crawler reads its requests from a single <ApiLink to="core/interface/IRequestManager">`IRequestManager`</ApiLink>, passed via the `requestManager` option. A <ApiLink to="core/class/RequestQueue">`RequestQueue`</ApiLink> is itself a request manager, so it can be passed directly. A read-only loader (such as <ApiLink to="core/class/RequestList">`RequestList`</ApiLink>) cannot — combine it with a queue into a tandem first, see the [Request manager tandem](#request-manager-tandem) section below. |
| 96 | + |
| 97 | +::: |
| 98 | + |
| 99 | +## Request loaders |
| 100 | + |
| 101 | +The <ApiLink to="core/interface/IRequestLoader">`IRequestLoader`</ApiLink> interface defines the foundation for fetching requests during a crawl. It provides methods for basic operations like retrieving the next request, marking requests as handled, and checking whether the loader is empty or finished. It is intentionally **read-only** — it does not allow adding new requests. Concrete implementations such as <ApiLink to="core/class/RequestList">`RequestList`</ApiLink> build on this interface to handle specific scenarios. You can create your own custom loader that reads from an external file, web endpoint, database, or any other data source. |
| 102 | + |
| 103 | +### Request list |
| 104 | + |
| 105 | +The <ApiLink to="core/class/RequestList">`RequestList`</ApiLink> manages a static list of URLs to crawl. The list is created for a single crawler run and, unlike a queue, cannot have requests added to or removed from it after initialization. It can hold a large number of URLs (even millions) with significantly lower overhead than enqueueing them one by one. |
| 106 | + |
| 107 | +Here is a basic example of working with the <ApiLink to="core/class/RequestList">`RequestList`</ApiLink>: |
| 108 | + |
| 109 | +<CodeBlock language="typescript"> |
| 110 | + {RlBasicSource} |
| 111 | +</CodeBlock> |
| 112 | + |
| 113 | +### Sitemap request loader |
| 114 | + |
| 115 | +The <ApiLink to="core/class/SitemapRequestLoader">`SitemapRequestLoader`</ApiLink> is a specialized request loader that reads URLs from sitemaps following the [Sitemaps protocol](https://www.sitemaps.org/protocol.html). It supports both XML and plain-text sitemap formats and is particularly useful when you want to crawl a website systematically by following its sitemap structure. Loading happens in the background, so crawling can start before the sitemap is fully parsed. |
| 116 | + |
| 117 | +:::note |
| 118 | + |
| 119 | +The `SitemapRequestLoader` is designed specifically for sitemaps that follow the standard Sitemaps protocol. HTML pages containing links are not supported by this loader — those should be handled by regular crawlers using the `enqueueLinks` functionality. |
| 120 | + |
| 121 | +::: |
| 122 | + |
| 123 | +The loader supports filtering URLs using glob patterns and regular expressions, allowing you to include or exclude specific types of URLs. |
| 124 | + |
| 125 | +<CodeBlock language="typescript"> |
| 126 | + {SitemapBasicSource} |
| 127 | +</CodeBlock> |
| 128 | + |
| 129 | +## Request managers |
| 130 | + |
| 131 | +The <ApiLink to="core/interface/IRequestManager">`IRequestManager`</ApiLink> interface extends `IRequestLoader` with **write** capabilities. In addition to reading requests, a request manager can add new requests and reclaim failed ones. This is essential for dynamic crawling, where new URLs emerge during the crawl, or when requests fail and need to be retried. The <ApiLink to="core/class/RequestQueue">`RequestQueue`</ApiLink> is the primary built-in request manager — see the [Request storage](./request-storage) guide for details. |
| 132 | + |
| 133 | +## Request manager tandem |
| 134 | + |
| 135 | +The <ApiLink to="core/class/RequestManagerTandem">`RequestManagerTandem`</ApiLink> class combines the read-only capabilities of an `IRequestLoader` (like <ApiLink to="core/class/RequestList">`RequestList`</ApiLink>) with the read-write capabilities of an `IRequestManager` (like <ApiLink to="core/class/RequestQueue">`RequestQueue`</ApiLink>). This is useful when you need to load initial requests from a static source (such as a file, sitemap, or database) and also dynamically add or retry requests during the crawl. |
| 136 | + |
| 137 | +Under the hood, the tandem checks whether the read-only loader still has pending requests. If so, each request from the loader is transferred to the manager (the queue) before being processed. Any newly added or reclaimed requests go directly to the manager side. Because every request passes through the queue, deduplication and retries are handled consistently and a single URL is not crawled multiple times. |
| 138 | + |
| 139 | +The easiest way to build a tandem is the <ApiLink to="core/interface/IRequestLoader#toTandem">`toTandem()`</ApiLink> helper available on the loaders. Called without arguments, it pairs the loader with the default <ApiLink to="core/class/RequestQueue">`RequestQueue`</ApiLink>; you can also pass a specific request manager to use instead. |
| 140 | + |
| 141 | +### Request list with request queue |
| 142 | + |
| 143 | +This setup is useful when you have a static list of URLs to crawl, but also need to handle dynamic requests discovered during the crawl. Requests from the <ApiLink to="core/class/RequestList">`RequestList`</ApiLink> are processed first by being enqueued into the <ApiLink to="core/class/RequestQueue">`RequestQueue`</ApiLink>, which handles persistence and retries. |
| 144 | + |
| 145 | +<Tabs groupId="request_manager_tandem"> |
| 146 | + <TabItem value="request_manager_tandem_helper" label="Using toTandem helper" default> |
| 147 | + <CodeBlock language="typescript"> |
| 148 | + {RlTandemHelperSource} |
| 149 | + </CodeBlock> |
| 150 | + </TabItem> |
| 151 | + <TabItem value="request_manager_tandem_explicit" label="Explicit usage"> |
| 152 | + <CodeBlock language="typescript"> |
| 153 | + {RlTandemExplicitSource} |
| 154 | + </CodeBlock> |
| 155 | + </TabItem> |
| 156 | +</Tabs> |
| 157 | + |
| 158 | +### Sitemap request loader with request queue |
| 159 | + |
| 160 | +Similarly, you can combine a <ApiLink to="core/class/SitemapRequestLoader">`SitemapRequestLoader`</ApiLink> with a <ApiLink to="core/class/RequestQueue">`RequestQueue`</ApiLink>. This is particularly useful when you want to crawl URLs from a sitemap while also handling dynamic requests discovered during the crawl. URLs from the sitemap are processed first by being enqueued into the queue, which handles persistence and retries. |
| 161 | + |
| 162 | +<Tabs groupId="sitemap_request_manager_tandem"> |
| 163 | + <TabItem value="sitemap_request_manager_tandem_helper" label="Using toTandem helper" default> |
| 164 | + <CodeBlock language="typescript"> |
| 165 | + {SitemapTandemHelperSource} |
| 166 | + </CodeBlock> |
| 167 | + </TabItem> |
| 168 | + <TabItem value="sitemap_request_manager_tandem_explicit" label="Explicit usage"> |
| 169 | + <CodeBlock language="typescript"> |
| 170 | + {SitemapTandemExplicitSource} |
| 171 | + </CodeBlock> |
| 172 | + </TabItem> |
| 173 | +</Tabs> |
| 174 | + |
| 175 | +## Conclusion |
| 176 | + |
| 177 | +This guide introduced the request loader abstractions: the read-only <ApiLink to="core/interface/IRequestLoader">`IRequestLoader`</ApiLink>, the writable <ApiLink to="core/interface/IRequestManager">`IRequestManager`</ApiLink>, and the <ApiLink to="core/class/RequestManagerTandem">`RequestManagerTandem`</ApiLink> that combines them, along with the <ApiLink to="core/class/RequestList">`RequestList`</ApiLink> and <ApiLink to="core/class/SitemapRequestLoader">`SitemapRequestLoader`</ApiLink> implementations. You also saw how to pair a loader with a queue using the `toTandem()` helper to handle both static and dynamically discovered requests. |
| 178 | + |
| 179 | +If you have questions or need assistance, feel free to reach out on our [GitHub](https://github.com/apify/crawlee) or join our [Discord community](https://discord.com/invite/jyEM2PRvMU). Happy scraping! |
0 commit comments