scrapfly-sdk 0.3.0

Async Rust client for the Scrapfly web scraping, screenshot, extraction and crawler APIs
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="Source of the Rust file `src/config/crawler.rs`."><title>crawler.rs - source</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2"href="../../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../../static.files/rustdoc-b7b9f40b.css"><meta name="rustdoc-vars" data-root-path="../../../" data-static-root-path="../../../static.files/" data-current-crate="scrapfly_sdk" data-themes="" data-resource-suffix="" data-rustdoc-version="1.95.0 (59807616e 2026-04-14)" data-channel="1.95.0" data-search-js="search-63369b7b.js" data-stringdex-js="stringdex-b897f86f.js" data-settings-js="settings-170eb4bf.js" ><script src="../../../static.files/storage-41dd4d93.js"></script><script defer src="../../../static.files/src-script-813739b1.js"></script><script defer src="../../../src-files.js"></script><script defer src="../../../static.files/main-5013f961.js"></script><noscript><link rel="stylesheet" href="../../../static.files/noscript-f7c3ffd8.css"></noscript><link rel="alternate icon" type="image/png" href="../../../static.files/favicon-32x32-eab170b8.png"><link rel="icon" type="image/svg+xml" href="../../../static.files/favicon-044be391.svg"></head><body class="rustdoc src"><a class="skip-main-content" href="#main-content">Skip to main content</a><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="sidebar"><div class="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><h1><div class="sub-heading">scrapfly_sdk/config/</div>crawler.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-3"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="doccomment">//! Crawler endpoint configuration — ported from `sdk/go/config_crawler.go`.
<a href=#2 id=2 data-nosnippet>2</a>
<a href=#3 id=3 data-nosnippet>3</a></span><span class="kw">use </span>std::collections::BTreeMap;
<a href=#4 id=4 data-nosnippet>4</a>
<a href=#5 id=5 data-nosnippet>5</a><span class="kw">use </span>serde::Serialize;
<a href=#6 id=6 data-nosnippet>6</a>
<a href=#7 id=7 data-nosnippet>7</a><span class="kw">use </span><span class="kw">crate</span>::enums::{CrawlerContentFormat, CrawlerWebhookEvent};
<a href=#8 id=8 data-nosnippet>8</a><span class="kw">use </span><span class="kw">crate</span>::error::ScrapflyError;
<a href=#9 id=9 data-nosnippet>9</a>
<a href=#10 id=10 data-nosnippet>10</a><span class="doccomment">/// Configuration for a `POST /crawl` request.
<a href=#11 id=11 data-nosnippet>11</a>///
<a href=#12 id=12 data-nosnippet>12</a>/// Exactly one URL source must be provided: `url` (seed crawl with
<a href=#13 id=13 data-nosnippet>13</a>/// discovery), `url_list` (in-memory list, no discovery), or
<a href=#14 id=14 data-nosnippet>14</a>/// `remote_url_list` (URL of a hosted text file fetched at crawl start, no
<a href=#15 id=15 data-nosnippet>15</a>/// discovery). Other fields default to server-side values when zero.
<a href=#16 id=16 data-nosnippet>16</a></span><span class="attr">#[derive(Debug, Clone, Default, Serialize)]
<a href=#17 id=17 data-nosnippet>17</a></span><span class="kw">pub struct </span>CrawlerConfig {
<a href=#18 id=18 data-nosnippet>18</a>    <span class="doccomment">/// Seed URL (must be HTTP/HTTPS). Mutually exclusive with `url_list`
<a href=#19 id=19 data-nosnippet>19</a>    /// and `remote_url_list`.
<a href=#20 id=20 data-nosnippet>20</a>    </span><span class="attr">#[serde(skip_serializing_if = <span class="string">"String::is_empty"</span>)]
<a href=#21 id=21 data-nosnippet>21</a>    </span><span class="kw">pub </span>url: String,
<a href=#22 id=22 data-nosnippet>22</a>    <span class="doccomment">/// Explicit URL list (no discovery). Mutually exclusive with `url`
<a href=#23 id=23 data-nosnippet>23</a>    /// and `remote_url_list`. When set, the SDK posts the request as
<a href=#24 id=24 data-nosnippet>24</a>    /// multipart/form-data so the URLs are uploaded as a streamed file
<a href=#25 id=25 data-nosnippet>25</a>    /// payload rather than inlined into the JSON body.
<a href=#26 id=26 data-nosnippet>26</a>    </span><span class="attr">#[serde(skip)]
<a href=#27 id=27 data-nosnippet>27</a>    </span><span class="kw">pub </span>url_list: Vec&lt;String&gt;,
<a href=#28 id=28 data-nosnippet>28</a>    <span class="doccomment">/// URL of a hosted text file (one URL per line) fetched at crawl
<a href=#29 id=29 data-nosnippet>29</a>    /// start. Mutually exclusive with `url` and `url_list`.
<a href=#30 id=30 data-nosnippet>30</a>    </span><span class="attr">#[serde(skip_serializing_if = <span class="string">"String::is_empty"</span>)]
<a href=#31 id=31 data-nosnippet>31</a>    </span><span class="kw">pub </span>remote_url_list: String,
<a href=#32 id=32 data-nosnippet>32</a>
<a href=#33 id=33 data-nosnippet>33</a>    <span class="doccomment">/// Max pages to crawl.
<a href=#34 id=34 data-nosnippet>34</a>    </span><span class="attr">#[serde(skip_serializing_if = <span class="string">"Option::is_none"</span>)]
<a href=#35 id=35 data-nosnippet>35</a>    </span><span class="kw">pub </span>page_limit: <span class="prelude-ty">Option</span>&lt;u32&gt;,
<a href=#36 id=36 data-nosnippet>36</a>    <span class="doccomment">/// Max link-follow depth.
<a href=#37 id=37 data-nosnippet>37</a>    </span><span class="attr">#[serde(skip_serializing_if = <span class="string">"Option::is_none"</span>)]
<a href=#38 id=38 data-nosnippet>38</a>    </span><span class="kw">pub </span>max_depth: <span class="prelude-ty">Option</span>&lt;u32&gt;,
<a href=#39 id=39 data-nosnippet>39</a>    <span class="doccomment">/// Max duration (seconds, 15..=10800).
<a href=#40 id=40 data-nosnippet>40</a>    </span><span class="attr">#[serde(skip_serializing_if = <span class="string">"Option::is_none"</span>)]
<a href=#41 id=41 data-nosnippet>41</a>    </span><span class="kw">pub </span>max_duration: <span class="prelude-ty">Option</span>&lt;u32&gt;,
<a href=#42 id=42 data-nosnippet>42</a>    <span class="doccomment">/// Max API credit to spend (0 = no limit).
<a href=#43 id=43 data-nosnippet>43</a>    </span><span class="attr">#[serde(skip_serializing_if = <span class="string">"Option::is_none"</span>)]
<a href=#44 id=44 data-nosnippet>44</a>    </span><span class="kw">pub </span>max_api_credit: <span class="prelude-ty">Option</span>&lt;u32&gt;,
<a href=#45 id=45 data-nosnippet>45</a>
<a href=#46 id=46 data-nosnippet>46</a>    <span class="doccomment">/// Exclude these URL paths (≤100 entries).
<a href=#47 id=47 data-nosnippet>47</a>    </span><span class="attr">#[serde(skip_serializing_if = <span class="string">"Vec::is_empty"</span>)]
<a href=#48 id=48 data-nosnippet>48</a>    </span><span class="kw">pub </span>exclude_paths: Vec&lt;String&gt;,
<a href=#49 id=49 data-nosnippet>49</a>    <span class="doccomment">/// Restrict crawl to these paths (≤100 entries).
<a href=#50 id=50 data-nosnippet>50</a>    </span><span class="attr">#[serde(skip_serializing_if = <span class="string">"Vec::is_empty"</span>)]
<a href=#51 id=51 data-nosnippet>51</a>    </span><span class="kw">pub </span>include_only_paths: Vec&lt;String&gt;,
<a href=#52 id=52 data-nosnippet>52</a>
<a href=#53 id=53 data-nosnippet>53</a>    <span class="doccomment">/// Ignore the seed URL's base-path restriction.
<a href=#54 id=54 data-nosnippet>54</a>    </span><span class="attr">#[serde(skip_serializing_if = <span class="string">"is_false"</span>)]
<a href=#55 id=55 data-nosnippet>55</a>    </span><span class="kw">pub </span>ignore_base_path_restriction: bool,
<a href=#56 id=56 data-nosnippet>56</a>    <span class="doccomment">/// Follow links to external domains.
<a href=#57 id=57 data-nosnippet>57</a>    </span><span class="attr">#[serde(skip_serializing_if = <span class="string">"is_false"</span>)]
<a href=#58 id=58 data-nosnippet>58</a>    </span><span class="kw">pub </span>follow_external_links: bool,
<a href=#59 id=59 data-nosnippet>59</a>    <span class="doccomment">/// Whitelist of external domains (≤250 entries).
<a href=#60 id=60 data-nosnippet>60</a>    </span><span class="attr">#[serde(skip_serializing_if = <span class="string">"Vec::is_empty"</span>)]
<a href=#61 id=61 data-nosnippet>61</a>    </span><span class="kw">pub </span>allowed_external_domains: Vec&lt;String&gt;,
<a href=#62 id=62 data-nosnippet>62</a>
<a href=#63 id=63 data-nosnippet>63</a>    <span class="doccomment">/// Tri-state: None = unset (server default true), Some(v) = explicit.
<a href=#64 id=64 data-nosnippet>64</a>    </span><span class="attr">#[serde(skip_serializing_if = <span class="string">"Option::is_none"</span>)]
<a href=#65 id=65 data-nosnippet>65</a>    </span><span class="kw">pub </span>follow_internal_subdomains: <span class="prelude-ty">Option</span>&lt;bool&gt;,
<a href=#66 id=66 data-nosnippet>66</a>    <span class="doccomment">/// Whitelist of internal subdomains (≤250 entries).
<a href=#67 id=67 data-nosnippet>67</a>    </span><span class="attr">#[serde(skip_serializing_if = <span class="string">"Vec::is_empty"</span>)]
<a href=#68 id=68 data-nosnippet>68</a>    </span><span class="kw">pub </span>allowed_internal_subdomains: Vec&lt;String&gt;,
<a href=#69 id=69 data-nosnippet>69</a>
<a href=#70 id=70 data-nosnippet>70</a>    <span class="doccomment">/// Request headers sent for every crawled page.
<a href=#71 id=71 data-nosnippet>71</a>    </span><span class="attr">#[serde(skip_serializing_if = <span class="string">"BTreeMap::is_empty"</span>)]
<a href=#72 id=72 data-nosnippet>72</a>    </span><span class="kw">pub </span>headers: BTreeMap&lt;String, String&gt;,
<a href=#73 id=73 data-nosnippet>73</a>    <span class="doccomment">/// Delay between requests (ms, 0..=15000).
<a href=#74 id=74 data-nosnippet>74</a>    </span><span class="attr">#[serde(skip_serializing_if = <span class="string">"Option::is_none"</span>)]
<a href=#75 id=75 data-nosnippet>75</a>    </span><span class="kw">pub </span>delay: <span class="prelude-ty">Option</span>&lt;u32&gt;,
<a href=#76 id=76 data-nosnippet>76</a>    <span class="doccomment">/// Override User-Agent.
<a href=#77 id=77 data-nosnippet>77</a>    </span><span class="attr">#[serde(skip_serializing_if = <span class="string">"Option::is_none"</span>)]
<a href=#78 id=78 data-nosnippet>78</a>    </span><span class="kw">pub </span>user_agent: <span class="prelude-ty">Option</span>&lt;String&gt;,
<a href=#79 id=79 data-nosnippet>79</a>    <span class="doccomment">/// Max concurrent workers.
<a href=#80 id=80 data-nosnippet>80</a>    </span><span class="attr">#[serde(skip_serializing_if = <span class="string">"Option::is_none"</span>)]
<a href=#81 id=81 data-nosnippet>81</a>    </span><span class="kw">pub </span>max_concurrency: <span class="prelude-ty">Option</span>&lt;u32&gt;,
<a href=#82 id=82 data-nosnippet>82</a>    <span class="doccomment">/// Rendering delay (ms, 0..=25000).
<a href=#83 id=83 data-nosnippet>83</a>    </span><span class="attr">#[serde(skip_serializing_if = <span class="string">"Option::is_none"</span>)]
<a href=#84 id=84 data-nosnippet>84</a>    </span><span class="kw">pub </span>rendering_delay: <span class="prelude-ty">Option</span>&lt;u32&gt;,
<a href=#85 id=85 data-nosnippet>85</a>
<a href=#86 id=86 data-nosnippet>86</a>    <span class="doccomment">/// Honor sitemaps.
<a href=#87 id=87 data-nosnippet>87</a>    </span><span class="attr">#[serde(skip_serializing_if = <span class="string">"is_false"</span>)]
<a href=#88 id=88 data-nosnippet>88</a>    </span><span class="kw">pub </span>use_sitemaps: bool,
<a href=#89 id=89 data-nosnippet>89</a>    <span class="doccomment">/// Follow `nofollow` links anyway.
<a href=#90 id=90 data-nosnippet>90</a>    </span><span class="attr">#[serde(skip_serializing_if = <span class="string">"is_false"</span>)]
<a href=#91 id=91 data-nosnippet>91</a>    </span><span class="kw">pub </span>ignore_no_follow: bool,
<a href=#92 id=92 data-nosnippet>92</a>
<a href=#93 id=93 data-nosnippet>93</a>    <span class="doccomment">/// Tri-state: None = server default (true).
<a href=#94 id=94 data-nosnippet>94</a>    </span><span class="attr">#[serde(skip_serializing_if = <span class="string">"Option::is_none"</span>)]
<a href=#95 id=95 data-nosnippet>95</a>    </span><span class="kw">pub </span>respect_robots_txt: <span class="prelude-ty">Option</span>&lt;bool&gt;,
<a href=#96 id=96 data-nosnippet>96</a>
<a href=#97 id=97 data-nosnippet>97</a>    <span class="doccomment">/// Enable cache.
<a href=#98 id=98 data-nosnippet>98</a>    </span><span class="attr">#[serde(skip_serializing_if = <span class="string">"is_false"</span>)]
<a href=#99 id=99 data-nosnippet>99</a>    </span><span class="kw">pub </span>cache: bool,
<a href=#100 id=100 data-nosnippet>100</a>    <span class="doccomment">/// Cache TTL seconds (0..=604800).
<a href=#101 id=101 data-nosnippet>101</a>    </span><span class="attr">#[serde(skip_serializing_if = <span class="string">"Option::is_none"</span>)]
<a href=#102 id=102 data-nosnippet>102</a>    </span><span class="kw">pub </span>cache_ttl: <span class="prelude-ty">Option</span>&lt;u32&gt;,
<a href=#103 id=103 data-nosnippet>103</a>    <span class="doccomment">/// Force cache refresh.
<a href=#104 id=104 data-nosnippet>104</a>    </span><span class="attr">#[serde(skip_serializing_if = <span class="string">"is_false"</span>)]
<a href=#105 id=105 data-nosnippet>105</a>    </span><span class="kw">pub </span>cache_clear: bool,
<a href=#106 id=106 data-nosnippet>106</a>
<a href=#107 id=107 data-nosnippet>107</a>    <span class="doccomment">/// Desired content formats.
<a href=#108 id=108 data-nosnippet>108</a>    </span><span class="attr">#[serde(skip_serializing_if = <span class="string">"Vec::is_empty"</span>)]
<a href=#109 id=109 data-nosnippet>109</a>    </span><span class="kw">pub </span>content_formats: Vec&lt;CrawlerContentFormat&gt;,
<a href=#110 id=110 data-nosnippet>110</a>    <span class="doccomment">/// Inline extraction rules.
<a href=#111 id=111 data-nosnippet>111</a>    </span><span class="attr">#[serde(skip_serializing_if = <span class="string">"Option::is_none"</span>)]
<a href=#112 id=112 data-nosnippet>112</a>    </span><span class="kw">pub </span>extraction_rules: <span class="prelude-ty">Option</span>&lt;serde_json::Value&gt;,
<a href=#113 id=113 data-nosnippet>113</a>
<a href=#114 id=114 data-nosnippet>114</a>    <span class="doccomment">/// Enable ASP bypass.
<a href=#115 id=115 data-nosnippet>115</a>    </span><span class="attr">#[serde(skip_serializing_if = <span class="string">"is_false"</span>)]
<a href=#116 id=116 data-nosnippet>116</a>    </span><span class="kw">pub </span>asp: bool,
<a href=#117 id=117 data-nosnippet>117</a>    <span class="doccomment">/// Proxy pool name.
<a href=#118 id=118 data-nosnippet>118</a>    </span><span class="attr">#[serde(skip_serializing_if = <span class="string">"Option::is_none"</span>)]
<a href=#119 id=119 data-nosnippet>119</a>    </span><span class="kw">pub </span>proxy_pool: <span class="prelude-ty">Option</span>&lt;String&gt;,
<a href=#120 id=120 data-nosnippet>120</a>    <span class="doccomment">/// Proxy country.
<a href=#121 id=121 data-nosnippet>121</a>    </span><span class="attr">#[serde(skip_serializing_if = <span class="string">"Option::is_none"</span>)]
<a href=#122 id=122 data-nosnippet>122</a>    </span><span class="kw">pub </span>country: <span class="prelude-ty">Option</span>&lt;String&gt;,
<a href=#123 id=123 data-nosnippet>123</a>
<a href=#124 id=124 data-nosnippet>124</a>    <span class="doccomment">/// Webhook name.
<a href=#125 id=125 data-nosnippet>125</a>    </span><span class="attr">#[serde(skip_serializing_if = <span class="string">"Option::is_none"</span>)]
<a href=#126 id=126 data-nosnippet>126</a>    </span><span class="kw">pub </span>webhook_name: <span class="prelude-ty">Option</span>&lt;String&gt;,
<a href=#127 id=127 data-nosnippet>127</a>    <span class="doccomment">/// Webhook events.
<a href=#128 id=128 data-nosnippet>128</a>    </span><span class="attr">#[serde(skip_serializing_if = <span class="string">"Vec::is_empty"</span>)]
<a href=#129 id=129 data-nosnippet>129</a>    </span><span class="kw">pub </span>webhook_events: Vec&lt;CrawlerWebhookEvent&gt;,
<a href=#130 id=130 data-nosnippet>130</a>}
<a href=#131 id=131 data-nosnippet>131</a>
<a href=#132 id=132 data-nosnippet>132</a><span class="kw">fn </span>is_false(v: <span class="kw-2">&amp;</span>bool) -&gt; bool {
<a href=#133 id=133 data-nosnippet>133</a>    !<span class="kw-2">*</span>v
<a href=#134 id=134 data-nosnippet>134</a>}
<a href=#135 id=135 data-nosnippet>135</a>
<a href=#136 id=136 data-nosnippet>136</a><span class="kw">impl </span>CrawlerConfig {
<a href=#137 id=137 data-nosnippet>137</a>    <span class="doccomment">/// Start a builder for `url` (seed-URL crawl with discovery).
<a href=#138 id=138 data-nosnippet>138</a>    </span><span class="kw">pub fn </span>builder(url: <span class="kw">impl </span>Into&lt;String&gt;) -&gt; CrawlerConfigBuilder {
<a href=#139 id=139 data-nosnippet>139</a>        CrawlerConfigBuilder {
<a href=#140 id=140 data-nosnippet>140</a>            cfg: CrawlerConfig {
<a href=#141 id=141 data-nosnippet>141</a>                url: url.into(),
<a href=#142 id=142 data-nosnippet>142</a>                ..Default::default()
<a href=#143 id=143 data-nosnippet>143</a>            },
<a href=#144 id=144 data-nosnippet>144</a>        }
<a href=#145 id=145 data-nosnippet>145</a>    }
<a href=#146 id=146 data-nosnippet>146</a>
<a href=#147 id=147 data-nosnippet>147</a>    <span class="doccomment">/// Start a builder for an explicit `url_list` (no discovery). The SDK
<a href=#148 id=148 data-nosnippet>148</a>    /// will post this configuration as multipart/form-data so the URLs are
<a href=#149 id=149 data-nosnippet>149</a>    /// uploaded as a streamed file payload.
<a href=#150 id=150 data-nosnippet>150</a>    </span><span class="kw">pub fn </span>builder_url_list(
<a href=#151 id=151 data-nosnippet>151</a>        urls: <span class="kw">impl </span>IntoIterator&lt;Item = <span class="kw">impl </span>Into&lt;String&gt;&gt;,
<a href=#152 id=152 data-nosnippet>152</a>    ) -&gt; CrawlerConfigBuilder {
<a href=#153 id=153 data-nosnippet>153</a>        CrawlerConfigBuilder {
<a href=#154 id=154 data-nosnippet>154</a>            cfg: CrawlerConfig {
<a href=#155 id=155 data-nosnippet>155</a>                url_list: urls.into_iter().map(Into::into).collect(),
<a href=#156 id=156 data-nosnippet>156</a>                ..Default::default()
<a href=#157 id=157 data-nosnippet>157</a>            },
<a href=#158 id=158 data-nosnippet>158</a>        }
<a href=#159 id=159 data-nosnippet>159</a>    }
<a href=#160 id=160 data-nosnippet>160</a>
<a href=#161 id=161 data-nosnippet>161</a>    <span class="doccomment">/// Start a builder for `remote_url_list` (no discovery, list fetched
<a href=#162 id=162 data-nosnippet>162</a>    /// from the given URL at crawl start).
<a href=#163 id=163 data-nosnippet>163</a>    </span><span class="kw">pub fn </span>builder_remote_url_list(url: <span class="kw">impl </span>Into&lt;String&gt;) -&gt; CrawlerConfigBuilder {
<a href=#164 id=164 data-nosnippet>164</a>        CrawlerConfigBuilder {
<a href=#165 id=165 data-nosnippet>165</a>            cfg: CrawlerConfig {
<a href=#166 id=166 data-nosnippet>166</a>                remote_url_list: url.into(),
<a href=#167 id=167 data-nosnippet>167</a>                ..Default::default()
<a href=#168 id=168 data-nosnippet>168</a>            },
<a href=#169 id=169 data-nosnippet>169</a>        }
<a href=#170 id=170 data-nosnippet>170</a>    }
<a href=#171 id=171 data-nosnippet>171</a>
<a href=#172 id=172 data-nosnippet>172</a>    <span class="doccomment">/// Validate numeric bounds + list sizes. Ported from
<a href=#173 id=173 data-nosnippet>173</a>    /// `sdk/go/config_crawler.go::validateBounds`.
<a href=#174 id=174 data-nosnippet>174</a>    </span><span class="kw">pub fn </span>validate(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="prelude-ty">Result</span>&lt;(), ScrapflyError&gt; {
<a href=#175 id=175 data-nosnippet>175</a>        <span class="kw">let </span>has_seed = !<span class="self">self</span>.url.is_empty();
<a href=#176 id=176 data-nosnippet>176</a>        <span class="kw">let </span>has_list = !<span class="self">self</span>.url_list.is_empty();
<a href=#177 id=177 data-nosnippet>177</a>        <span class="kw">let </span>has_remote = !<span class="self">self</span>.remote_url_list.is_empty();
<a href=#178 id=178 data-nosnippet>178</a>        <span class="kw">let </span>count = (has_seed <span class="kw">as </span>u8) + (has_list <span class="kw">as </span>u8) + (has_remote <span class="kw">as </span>u8);
<a href=#179 id=179 data-nosnippet>179</a>        <span class="kw">if </span>count == <span class="number">0 </span>{
<a href=#180 id=180 data-nosnippet>180</a>            <span class="kw">return </span><span class="prelude-val">Err</span>(ScrapflyError::Config(
<a href=#181 id=181 data-nosnippet>181</a>                <span class="string">"provide one of url, url_list, or remote_url_list"</span>.into(),
<a href=#182 id=182 data-nosnippet>182</a>            ));
<a href=#183 id=183 data-nosnippet>183</a>        }
<a href=#184 id=184 data-nosnippet>184</a>        <span class="kw">if </span>count &gt; <span class="number">1 </span>{
<a href=#185 id=185 data-nosnippet>185</a>            <span class="kw">return </span><span class="prelude-val">Err</span>(ScrapflyError::Config(
<a href=#186 id=186 data-nosnippet>186</a>                <span class="string">"only one of url, url_list, or remote_url_list can be set"</span>.into(),
<a href=#187 id=187 data-nosnippet>187</a>            ));
<a href=#188 id=188 data-nosnippet>188</a>        }
<a href=#189 id=189 data-nosnippet>189</a>        <span class="kw">if let </span><span class="prelude-val">Some</span>(d) = <span class="self">self</span>.max_duration {
<a href=#190 id=190 data-nosnippet>190</a>            <span class="kw">if </span>!(<span class="number">15</span>..=<span class="number">10800</span>).contains(<span class="kw-2">&amp;</span>d) {
<a href=#191 id=191 data-nosnippet>191</a>                <span class="kw">return </span><span class="prelude-val">Err</span>(ScrapflyError::Config(<span class="macro">format!</span>(
<a href=#192 id=192 data-nosnippet>192</a>                    <span class="string">"max_duration must be between 15 and 10800 seconds, got {}"</span>,
<a href=#193 id=193 data-nosnippet>193</a>                    d
<a href=#194 id=194 data-nosnippet>194</a>                )));
<a href=#195 id=195 data-nosnippet>195</a>            }
<a href=#196 id=196 data-nosnippet>196</a>        }
<a href=#197 id=197 data-nosnippet>197</a>        <span class="kw">if let </span><span class="prelude-val">Some</span>(rd) = <span class="self">self</span>.rendering_delay {
<a href=#198 id=198 data-nosnippet>198</a>            <span class="kw">if </span>rd &gt; <span class="number">25000 </span>{
<a href=#199 id=199 data-nosnippet>199</a>                <span class="kw">return </span><span class="prelude-val">Err</span>(ScrapflyError::Config(<span class="macro">format!</span>(
<a href=#200 id=200 data-nosnippet>200</a>                    <span class="string">"rendering_delay must be between 0 and 25000 ms, got {}"</span>,
<a href=#201 id=201 data-nosnippet>201</a>                    rd
<a href=#202 id=202 data-nosnippet>202</a>                )));
<a href=#203 id=203 data-nosnippet>203</a>            }
<a href=#204 id=204 data-nosnippet>204</a>        }
<a href=#205 id=205 data-nosnippet>205</a>        <span class="kw">if let </span><span class="prelude-val">Some</span>(delay) = <span class="self">self</span>.delay {
<a href=#206 id=206 data-nosnippet>206</a>            <span class="kw">if </span>delay &gt; <span class="number">15000 </span>{
<a href=#207 id=207 data-nosnippet>207</a>                <span class="kw">return </span><span class="prelude-val">Err</span>(ScrapflyError::Config(<span class="macro">format!</span>(
<a href=#208 id=208 data-nosnippet>208</a>                    <span class="string">"delay must be between 0 and 15000 ms, got {}"</span>,
<a href=#209 id=209 data-nosnippet>209</a>                    delay
<a href=#210 id=210 data-nosnippet>210</a>                )));
<a href=#211 id=211 data-nosnippet>211</a>            }
<a href=#212 id=212 data-nosnippet>212</a>        }
<a href=#213 id=213 data-nosnippet>213</a>        <span class="kw">if let </span><span class="prelude-val">Some</span>(ttl) = <span class="self">self</span>.cache_ttl {
<a href=#214 id=214 data-nosnippet>214</a>            <span class="kw">if </span>ttl &gt; <span class="number">604800 </span>{
<a href=#215 id=215 data-nosnippet>215</a>                <span class="kw">return </span><span class="prelude-val">Err</span>(ScrapflyError::Config(<span class="macro">format!</span>(
<a href=#216 id=216 data-nosnippet>216</a>                    <span class="string">"cache_ttl must be between 0 and 604800 seconds, got {}"</span>,
<a href=#217 id=217 data-nosnippet>217</a>                    ttl
<a href=#218 id=218 data-nosnippet>218</a>                )));
<a href=#219 id=219 data-nosnippet>219</a>            }
<a href=#220 id=220 data-nosnippet>220</a>        }
<a href=#221 id=221 data-nosnippet>221</a>        <span class="kw">if </span><span class="self">self</span>.exclude_paths.len() &gt; <span class="number">100 </span>{
<a href=#222 id=222 data-nosnippet>222</a>            <span class="kw">return </span><span class="prelude-val">Err</span>(ScrapflyError::Config(<span class="macro">format!</span>(
<a href=#223 id=223 data-nosnippet>223</a>                <span class="string">"exclude_paths is limited to 100 entries, got {}"</span>,
<a href=#224 id=224 data-nosnippet>224</a>                <span class="self">self</span>.exclude_paths.len()
<a href=#225 id=225 data-nosnippet>225</a>            )));
<a href=#226 id=226 data-nosnippet>226</a>        }
<a href=#227 id=227 data-nosnippet>227</a>        <span class="kw">if </span><span class="self">self</span>.include_only_paths.len() &gt; <span class="number">100 </span>{
<a href=#228 id=228 data-nosnippet>228</a>            <span class="kw">return </span><span class="prelude-val">Err</span>(ScrapflyError::Config(<span class="macro">format!</span>(
<a href=#229 id=229 data-nosnippet>229</a>                <span class="string">"include_only_paths is limited to 100 entries, got {}"</span>,
<a href=#230 id=230 data-nosnippet>230</a>                <span class="self">self</span>.include_only_paths.len()
<a href=#231 id=231 data-nosnippet>231</a>            )));
<a href=#232 id=232 data-nosnippet>232</a>        }
<a href=#233 id=233 data-nosnippet>233</a>        <span class="kw">if </span>!<span class="self">self</span>.exclude_paths.is_empty() &amp;&amp; !<span class="self">self</span>.include_only_paths.is_empty() {
<a href=#234 id=234 data-nosnippet>234</a>            <span class="kw">return </span><span class="prelude-val">Err</span>(ScrapflyError::Config(
<a href=#235 id=235 data-nosnippet>235</a>                <span class="string">"exclude_paths and include_only_paths are mutually exclusive"</span>.into(),
<a href=#236 id=236 data-nosnippet>236</a>            ));
<a href=#237 id=237 data-nosnippet>237</a>        }
<a href=#238 id=238 data-nosnippet>238</a>        <span class="kw">if </span><span class="self">self</span>.allowed_external_domains.len() &gt; <span class="number">250 </span>{
<a href=#239 id=239 data-nosnippet>239</a>            <span class="kw">return </span><span class="prelude-val">Err</span>(ScrapflyError::Config(<span class="macro">format!</span>(
<a href=#240 id=240 data-nosnippet>240</a>                <span class="string">"allowed_external_domains is limited to 250 entries, got {}"</span>,
<a href=#241 id=241 data-nosnippet>241</a>                <span class="self">self</span>.allowed_external_domains.len()
<a href=#242 id=242 data-nosnippet>242</a>            )));
<a href=#243 id=243 data-nosnippet>243</a>        }
<a href=#244 id=244 data-nosnippet>244</a>        <span class="kw">if </span><span class="self">self</span>.allowed_internal_subdomains.len() &gt; <span class="number">250 </span>{
<a href=#245 id=245 data-nosnippet>245</a>            <span class="kw">return </span><span class="prelude-val">Err</span>(ScrapflyError::Config(<span class="macro">format!</span>(
<a href=#246 id=246 data-nosnippet>246</a>                <span class="string">"allowed_internal_subdomains is limited to 250 entries, got {}"</span>,
<a href=#247 id=247 data-nosnippet>247</a>                <span class="self">self</span>.allowed_internal_subdomains.len()
<a href=#248 id=248 data-nosnippet>248</a>            )));
<a href=#249 id=249 data-nosnippet>249</a>        }
<a href=#250 id=250 data-nosnippet>250</a>        <span class="prelude-val">Ok</span>(())
<a href=#251 id=251 data-nosnippet>251</a>    }
<a href=#252 id=252 data-nosnippet>252</a>
<a href=#253 id=253 data-nosnippet>253</a>    <span class="doccomment">/// Serialize into the JSON body the crawler endpoint expects. Used
<a href=#254 id=254 data-nosnippet>254</a>    /// for seed-URL crawls and remote_url_list crawls. For in-memory URL
<a href=#255 id=255 data-nosnippet>255</a>    /// lists the SDK switches to multipart (see `to_multipart_body`).
<a href=#256 id=256 data-nosnippet>256</a>    </span><span class="kw">pub fn </span>to_json_body(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="prelude-ty">Result</span>&lt;Vec&lt;u8&gt;, ScrapflyError&gt; {
<a href=#257 id=257 data-nosnippet>257</a>        <span class="self">self</span>.validate()<span class="question-mark">?</span>;
<a href=#258 id=258 data-nosnippet>258</a>        <span class="prelude-val">Ok</span>(serde_json::to_vec(<span class="self">self</span>)<span class="question-mark">?</span>)
<a href=#259 id=259 data-nosnippet>259</a>    }
<a href=#260 id=260 data-nosnippet>260</a>
<a href=#261 id=261 data-nosnippet>261</a>    <span class="doccomment">/// Build a multipart/form-data body for `POST /crawl` when an in-memory
<a href=#262 id=262 data-nosnippet>262</a>    /// `url_list` is supplied. The `config` part carries the JSON config
<a href=#263 id=263 data-nosnippet>263</a>    /// (without url_list) and the `urls` part carries the URLs as
<a href=#264 id=264 data-nosnippet>264</a>    /// text/plain, one per line. Returns the body bytes and the matching
<a href=#265 id=265 data-nosnippet>265</a>    /// Content-Type header (with the boundary baked in).
<a href=#266 id=266 data-nosnippet>266</a>    </span><span class="kw">pub fn </span>to_multipart_body(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="prelude-ty">Result</span>&lt;(Vec&lt;u8&gt;, String), ScrapflyError&gt; {
<a href=#267 id=267 data-nosnippet>267</a>        <span class="self">self</span>.validate()<span class="question-mark">?</span>;
<a href=#268 id=268 data-nosnippet>268</a>        <span class="kw">if </span><span class="self">self</span>.url_list.is_empty() {
<a href=#269 id=269 data-nosnippet>269</a>            <span class="kw">return </span><span class="prelude-val">Err</span>(ScrapflyError::Config(
<a href=#270 id=270 data-nosnippet>270</a>                <span class="string">"to_multipart_body requires url_list to be set"</span>.into(),
<a href=#271 id=271 data-nosnippet>271</a>            ));
<a href=#272 id=272 data-nosnippet>272</a>        }
<a href=#273 id=273 data-nosnippet>273</a>
<a href=#274 id=274 data-nosnippet>274</a>        <span class="comment">// Boundary derived from the SDK name + a short random tail. The
<a href=#275 id=275 data-nosnippet>275</a>        // value is opaque to the server; it just needs to be unique within
<a href=#276 id=276 data-nosnippet>276</a>        // the request and absent from the body content (URLs and JSON).
<a href=#277 id=277 data-nosnippet>277</a>        </span><span class="kw">let </span>boundary = <span class="macro">format!</span>(<span class="string">"scrapfly-rs-{:016x}"</span>, rand_u64());
<a href=#278 id=278 data-nosnippet>278</a>        <span class="kw">let </span>config_json = serde_json::to_vec(<span class="self">self</span>)<span class="question-mark">?</span>;
<a href=#279 id=279 data-nosnippet>279</a>        <span class="kw">let </span>urls_blob = <span class="self">self</span>.url_list.join(<span class="string">"\n"</span>);
<a href=#280 id=280 data-nosnippet>280</a>
<a href=#281 id=281 data-nosnippet>281</a>        <span class="kw">let </span><span class="kw-2">mut </span>buf: Vec&lt;u8&gt; = Vec::with_capacity(config_json.len() + urls_blob.len() + <span class="number">256</span>);
<a href=#282 id=282 data-nosnippet>282</a>        buf.extend_from_slice(<span class="macro">format!</span>(<span class="string">"--{}\r\n"</span>, boundary).as_bytes());
<a href=#283 id=283 data-nosnippet>283</a>        buf.extend_from_slice(
<a href=#284 id=284 data-nosnippet>284</a>            <span class="string">b"Content-Disposition: form-data; name=\"config\"; filename=\"config.json\"\r\n"</span>,
<a href=#285 id=285 data-nosnippet>285</a>        );
<a href=#286 id=286 data-nosnippet>286</a>        buf.extend_from_slice(<span class="string">b"Content-Type: application/json\r\n\r\n"</span>);
<a href=#287 id=287 data-nosnippet>287</a>        buf.extend_from_slice(<span class="kw-2">&amp;</span>config_json);
<a href=#288 id=288 data-nosnippet>288</a>        buf.extend_from_slice(<span class="string">b"\r\n"</span>);
<a href=#289 id=289 data-nosnippet>289</a>        buf.extend_from_slice(<span class="macro">format!</span>(<span class="string">"--{}\r\n"</span>, boundary).as_bytes());
<a href=#290 id=290 data-nosnippet>290</a>        buf.extend_from_slice(
<a href=#291 id=291 data-nosnippet>291</a>            <span class="string">b"Content-Disposition: form-data; name=\"urls\"; filename=\"urls.txt\"\r\n"</span>,
<a href=#292 id=292 data-nosnippet>292</a>        );
<a href=#293 id=293 data-nosnippet>293</a>        buf.extend_from_slice(<span class="string">b"Content-Type: text/plain\r\n\r\n"</span>);
<a href=#294 id=294 data-nosnippet>294</a>        buf.extend_from_slice(urls_blob.as_bytes());
<a href=#295 id=295 data-nosnippet>295</a>        buf.extend_from_slice(<span class="string">b"\r\n"</span>);
<a href=#296 id=296 data-nosnippet>296</a>        buf.extend_from_slice(<span class="macro">format!</span>(<span class="string">"--{}--\r\n"</span>, boundary).as_bytes());
<a href=#297 id=297 data-nosnippet>297</a>
<a href=#298 id=298 data-nosnippet>298</a>        <span class="prelude-val">Ok</span>((buf, <span class="macro">format!</span>(<span class="string">"multipart/form-data; boundary={}"</span>, boundary)))
<a href=#299 id=299 data-nosnippet>299</a>    }
<a href=#300 id=300 data-nosnippet>300</a>}
<a href=#301 id=301 data-nosnippet>301</a>
<a href=#302 id=302 data-nosnippet>302</a><span class="comment">// Small non-crypto random for the multipart boundary. We use a fast,
<a href=#303 id=303 data-nosnippet>303</a>// dependency-free PRNG seeded from the system clock — the boundary just
<a href=#304 id=304 data-nosnippet>304</a>// needs to be unique within the request, not cryptographically secure.
<a href=#305 id=305 data-nosnippet>305</a></span><span class="kw">fn </span>rand_u64() -&gt; u64 {
<a href=#306 id=306 data-nosnippet>306</a>    <span class="kw">use </span>std::time::{SystemTime, UNIX_EPOCH};
<a href=#307 id=307 data-nosnippet>307</a>    <span class="kw">let </span>nanos = SystemTime::now()
<a href=#308 id=308 data-nosnippet>308</a>        .duration_since(UNIX_EPOCH)
<a href=#309 id=309 data-nosnippet>309</a>        .map(|d| d.as_nanos() <span class="kw">as </span>u64)
<a href=#310 id=310 data-nosnippet>310</a>        .unwrap_or(<span class="number">0</span>);
<a href=#311 id=311 data-nosnippet>311</a>    <span class="comment">// splitmix64 step from the source paper — adequate for boundary tags.
<a href=#312 id=312 data-nosnippet>312</a>    </span><span class="kw">let </span><span class="kw-2">mut </span>z = nanos.wrapping_add(<span class="number">0x9E3779B97F4A7C15</span>);
<a href=#313 id=313 data-nosnippet>313</a>    z = (z ^ (z &gt;&gt; <span class="number">30</span>)).wrapping_mul(<span class="number">0xBF58476D1CE4E5B9</span>);
<a href=#314 id=314 data-nosnippet>314</a>    z = (z ^ (z &gt;&gt; <span class="number">27</span>)).wrapping_mul(<span class="number">0x94D049BB133111EB</span>);
<a href=#315 id=315 data-nosnippet>315</a>    z ^ (z &gt;&gt; <span class="number">31</span>)
<a href=#316 id=316 data-nosnippet>316</a>}
<a href=#317 id=317 data-nosnippet>317</a>
<a href=#318 id=318 data-nosnippet>318</a><span class="doccomment">/// Builder for [`CrawlerConfig`].
<a href=#319 id=319 data-nosnippet>319</a></span><span class="attr">#[derive(Debug, Clone)]
<a href=#320 id=320 data-nosnippet>320</a></span><span class="kw">pub struct </span>CrawlerConfigBuilder {
<a href=#321 id=321 data-nosnippet>321</a>    cfg: CrawlerConfig,
<a href=#322 id=322 data-nosnippet>322</a>}
<a href=#323 id=323 data-nosnippet>323</a>
<a href=#324 id=324 data-nosnippet>324</a><span class="kw">impl </span>CrawlerConfigBuilder {
<a href=#325 id=325 data-nosnippet>325</a>    <span class="doccomment">/// Set page limit.
<a href=#326 id=326 data-nosnippet>326</a>    </span><span class="kw">pub fn </span>page_limit(<span class="kw-2">mut </span><span class="self">self</span>, v: u32) -&gt; <span class="self">Self </span>{
<a href=#327 id=327 data-nosnippet>327</a>        <span class="self">self</span>.cfg.page_limit = <span class="prelude-val">Some</span>(v);
<a href=#328 id=328 data-nosnippet>328</a>        <span class="self">self
<a href=#329 id=329 data-nosnippet>329</a>    </span>}
<a href=#330 id=330 data-nosnippet>330</a>    <span class="doccomment">/// Set max depth.
<a href=#331 id=331 data-nosnippet>331</a>    </span><span class="kw">pub fn </span>max_depth(<span class="kw-2">mut </span><span class="self">self</span>, v: u32) -&gt; <span class="self">Self </span>{
<a href=#332 id=332 data-nosnippet>332</a>        <span class="self">self</span>.cfg.max_depth = <span class="prelude-val">Some</span>(v);
<a href=#333 id=333 data-nosnippet>333</a>        <span class="self">self
<a href=#334 id=334 data-nosnippet>334</a>    </span>}
<a href=#335 id=335 data-nosnippet>335</a>    <span class="doccomment">/// Set max duration (seconds).
<a href=#336 id=336 data-nosnippet>336</a>    </span><span class="kw">pub fn </span>max_duration(<span class="kw-2">mut </span><span class="self">self</span>, v: u32) -&gt; <span class="self">Self </span>{
<a href=#337 id=337 data-nosnippet>337</a>        <span class="self">self</span>.cfg.max_duration = <span class="prelude-val">Some</span>(v);
<a href=#338 id=338 data-nosnippet>338</a>        <span class="self">self
<a href=#339 id=339 data-nosnippet>339</a>    </span>}
<a href=#340 id=340 data-nosnippet>340</a>    <span class="doccomment">/// Set max API credit.
<a href=#341 id=341 data-nosnippet>341</a>    </span><span class="kw">pub fn </span>max_api_credit(<span class="kw-2">mut </span><span class="self">self</span>, v: u32) -&gt; <span class="self">Self </span>{
<a href=#342 id=342 data-nosnippet>342</a>        <span class="self">self</span>.cfg.max_api_credit = <span class="prelude-val">Some</span>(v);
<a href=#343 id=343 data-nosnippet>343</a>        <span class="self">self
<a href=#344 id=344 data-nosnippet>344</a>    </span>}
<a href=#345 id=345 data-nosnippet>345</a>    <span class="doccomment">/// Set exclude paths.
<a href=#346 id=346 data-nosnippet>346</a>    </span><span class="kw">pub fn </span>exclude_paths(<span class="kw-2">mut </span><span class="self">self</span>, v: Vec&lt;String&gt;) -&gt; <span class="self">Self </span>{
<a href=#347 id=347 data-nosnippet>347</a>        <span class="self">self</span>.cfg.exclude_paths = v;
<a href=#348 id=348 data-nosnippet>348</a>        <span class="self">self
<a href=#349 id=349 data-nosnippet>349</a>    </span>}
<a href=#350 id=350 data-nosnippet>350</a>    <span class="doccomment">/// Set include-only paths.
<a href=#351 id=351 data-nosnippet>351</a>    </span><span class="kw">pub fn </span>include_only_paths(<span class="kw-2">mut </span><span class="self">self</span>, v: Vec&lt;String&gt;) -&gt; <span class="self">Self </span>{
<a href=#352 id=352 data-nosnippet>352</a>        <span class="self">self</span>.cfg.include_only_paths = v;
<a href=#353 id=353 data-nosnippet>353</a>        <span class="self">self
<a href=#354 id=354 data-nosnippet>354</a>    </span>}
<a href=#355 id=355 data-nosnippet>355</a>    <span class="doccomment">/// Ignore base-path restriction.
<a href=#356 id=356 data-nosnippet>356</a>    </span><span class="kw">pub fn </span>ignore_base_path_restriction(<span class="kw-2">mut </span><span class="self">self</span>, v: bool) -&gt; <span class="self">Self </span>{
<a href=#357 id=357 data-nosnippet>357</a>        <span class="self">self</span>.cfg.ignore_base_path_restriction = v;
<a href=#358 id=358 data-nosnippet>358</a>        <span class="self">self
<a href=#359 id=359 data-nosnippet>359</a>    </span>}
<a href=#360 id=360 data-nosnippet>360</a>    <span class="doccomment">/// Follow external links.
<a href=#361 id=361 data-nosnippet>361</a>    </span><span class="kw">pub fn </span>follow_external_links(<span class="kw-2">mut </span><span class="self">self</span>, v: bool) -&gt; <span class="self">Self </span>{
<a href=#362 id=362 data-nosnippet>362</a>        <span class="self">self</span>.cfg.follow_external_links = v;
<a href=#363 id=363 data-nosnippet>363</a>        <span class="self">self
<a href=#364 id=364 data-nosnippet>364</a>    </span>}
<a href=#365 id=365 data-nosnippet>365</a>    <span class="doccomment">/// Set allowed external domains.
<a href=#366 id=366 data-nosnippet>366</a>    </span><span class="kw">pub fn </span>allowed_external_domains(<span class="kw-2">mut </span><span class="self">self</span>, v: Vec&lt;String&gt;) -&gt; <span class="self">Self </span>{
<a href=#367 id=367 data-nosnippet>367</a>        <span class="self">self</span>.cfg.allowed_external_domains = v;
<a href=#368 id=368 data-nosnippet>368</a>        <span class="self">self
<a href=#369 id=369 data-nosnippet>369</a>    </span>}
<a href=#370 id=370 data-nosnippet>370</a>    <span class="doccomment">/// Tri-state follow-internal-subdomains.
<a href=#371 id=371 data-nosnippet>371</a>    </span><span class="kw">pub fn </span>follow_internal_subdomains(<span class="kw-2">mut </span><span class="self">self</span>, v: bool) -&gt; <span class="self">Self </span>{
<a href=#372 id=372 data-nosnippet>372</a>        <span class="self">self</span>.cfg.follow_internal_subdomains = <span class="prelude-val">Some</span>(v);
<a href=#373 id=373 data-nosnippet>373</a>        <span class="self">self
<a href=#374 id=374 data-nosnippet>374</a>    </span>}
<a href=#375 id=375 data-nosnippet>375</a>    <span class="doccomment">/// Set allowed internal subdomains.
<a href=#376 id=376 data-nosnippet>376</a>    </span><span class="kw">pub fn </span>allowed_internal_subdomains(<span class="kw-2">mut </span><span class="self">self</span>, v: Vec&lt;String&gt;) -&gt; <span class="self">Self </span>{
<a href=#377 id=377 data-nosnippet>377</a>        <span class="self">self</span>.cfg.allowed_internal_subdomains = v;
<a href=#378 id=378 data-nosnippet>378</a>        <span class="self">self
<a href=#379 id=379 data-nosnippet>379</a>    </span>}
<a href=#380 id=380 data-nosnippet>380</a>    <span class="doccomment">/// Add header.
<a href=#381 id=381 data-nosnippet>381</a>    </span><span class="kw">pub fn </span>header(<span class="kw-2">mut </span><span class="self">self</span>, k: <span class="kw">impl </span>Into&lt;String&gt;, v: <span class="kw">impl </span>Into&lt;String&gt;) -&gt; <span class="self">Self </span>{
<a href=#382 id=382 data-nosnippet>382</a>        <span class="self">self</span>.cfg.headers.insert(k.into(), v.into());
<a href=#383 id=383 data-nosnippet>383</a>        <span class="self">self
<a href=#384 id=384 data-nosnippet>384</a>    </span>}
<a href=#385 id=385 data-nosnippet>385</a>    <span class="doccomment">/// Set delay (ms).
<a href=#386 id=386 data-nosnippet>386</a>    </span><span class="kw">pub fn </span>delay(<span class="kw-2">mut </span><span class="self">self</span>, v: u32) -&gt; <span class="self">Self </span>{
<a href=#387 id=387 data-nosnippet>387</a>        <span class="self">self</span>.cfg.delay = <span class="prelude-val">Some</span>(v);
<a href=#388 id=388 data-nosnippet>388</a>        <span class="self">self
<a href=#389 id=389 data-nosnippet>389</a>    </span>}
<a href=#390 id=390 data-nosnippet>390</a>    <span class="doccomment">/// Set User-Agent.
<a href=#391 id=391 data-nosnippet>391</a>    </span><span class="kw">pub fn </span>user_agent(<span class="kw-2">mut </span><span class="self">self</span>, v: <span class="kw">impl </span>Into&lt;String&gt;) -&gt; <span class="self">Self </span>{
<a href=#392 id=392 data-nosnippet>392</a>        <span class="self">self</span>.cfg.user_agent = <span class="prelude-val">Some</span>(v.into());
<a href=#393 id=393 data-nosnippet>393</a>        <span class="self">self
<a href=#394 id=394 data-nosnippet>394</a>    </span>}
<a href=#395 id=395 data-nosnippet>395</a>    <span class="doccomment">/// Set max concurrency.
<a href=#396 id=396 data-nosnippet>396</a>    </span><span class="kw">pub fn </span>max_concurrency(<span class="kw-2">mut </span><span class="self">self</span>, v: u32) -&gt; <span class="self">Self </span>{
<a href=#397 id=397 data-nosnippet>397</a>        <span class="self">self</span>.cfg.max_concurrency = <span class="prelude-val">Some</span>(v);
<a href=#398 id=398 data-nosnippet>398</a>        <span class="self">self
<a href=#399 id=399 data-nosnippet>399</a>    </span>}
<a href=#400 id=400 data-nosnippet>400</a>    <span class="doccomment">/// Set rendering delay (ms).
<a href=#401 id=401 data-nosnippet>401</a>    </span><span class="kw">pub fn </span>rendering_delay(<span class="kw-2">mut </span><span class="self">self</span>, v: u32) -&gt; <span class="self">Self </span>{
<a href=#402 id=402 data-nosnippet>402</a>        <span class="self">self</span>.cfg.rendering_delay = <span class="prelude-val">Some</span>(v);
<a href=#403 id=403 data-nosnippet>403</a>        <span class="self">self
<a href=#404 id=404 data-nosnippet>404</a>    </span>}
<a href=#405 id=405 data-nosnippet>405</a>    <span class="doccomment">/// Honor sitemaps.
<a href=#406 id=406 data-nosnippet>406</a>    </span><span class="kw">pub fn </span>use_sitemaps(<span class="kw-2">mut </span><span class="self">self</span>, v: bool) -&gt; <span class="self">Self </span>{
<a href=#407 id=407 data-nosnippet>407</a>        <span class="self">self</span>.cfg.use_sitemaps = v;
<a href=#408 id=408 data-nosnippet>408</a>        <span class="self">self
<a href=#409 id=409 data-nosnippet>409</a>    </span>}
<a href=#410 id=410 data-nosnippet>410</a>    <span class="doccomment">/// Ignore nofollow.
<a href=#411 id=411 data-nosnippet>411</a>    </span><span class="kw">pub fn </span>ignore_no_follow(<span class="kw-2">mut </span><span class="self">self</span>, v: bool) -&gt; <span class="self">Self </span>{
<a href=#412 id=412 data-nosnippet>412</a>        <span class="self">self</span>.cfg.ignore_no_follow = v;
<a href=#413 id=413 data-nosnippet>413</a>        <span class="self">self
<a href=#414 id=414 data-nosnippet>414</a>    </span>}
<a href=#415 id=415 data-nosnippet>415</a>    <span class="doccomment">/// Tri-state respect-robots-txt.
<a href=#416 id=416 data-nosnippet>416</a>    </span><span class="kw">pub fn </span>respect_robots_txt(<span class="kw-2">mut </span><span class="self">self</span>, v: bool) -&gt; <span class="self">Self </span>{
<a href=#417 id=417 data-nosnippet>417</a>        <span class="self">self</span>.cfg.respect_robots_txt = <span class="prelude-val">Some</span>(v);
<a href=#418 id=418 data-nosnippet>418</a>        <span class="self">self
<a href=#419 id=419 data-nosnippet>419</a>    </span>}
<a href=#420 id=420 data-nosnippet>420</a>    <span class="doccomment">/// Enable cache.
<a href=#421 id=421 data-nosnippet>421</a>    </span><span class="kw">pub fn </span>cache(<span class="kw-2">mut </span><span class="self">self</span>, v: bool) -&gt; <span class="self">Self </span>{
<a href=#422 id=422 data-nosnippet>422</a>        <span class="self">self</span>.cfg.cache = v;
<a href=#423 id=423 data-nosnippet>423</a>        <span class="self">self
<a href=#424 id=424 data-nosnippet>424</a>    </span>}
<a href=#425 id=425 data-nosnippet>425</a>    <span class="doccomment">/// Cache TTL.
<a href=#426 id=426 data-nosnippet>426</a>    </span><span class="kw">pub fn </span>cache_ttl(<span class="kw-2">mut </span><span class="self">self</span>, v: u32) -&gt; <span class="self">Self </span>{
<a href=#427 id=427 data-nosnippet>427</a>        <span class="self">self</span>.cfg.cache_ttl = <span class="prelude-val">Some</span>(v);
<a href=#428 id=428 data-nosnippet>428</a>        <span class="self">self
<a href=#429 id=429 data-nosnippet>429</a>    </span>}
<a href=#430 id=430 data-nosnippet>430</a>    <span class="doccomment">/// Force cache refresh.
<a href=#431 id=431 data-nosnippet>431</a>    </span><span class="kw">pub fn </span>cache_clear(<span class="kw-2">mut </span><span class="self">self</span>, v: bool) -&gt; <span class="self">Self </span>{
<a href=#432 id=432 data-nosnippet>432</a>        <span class="self">self</span>.cfg.cache_clear = v;
<a href=#433 id=433 data-nosnippet>433</a>        <span class="self">self
<a href=#434 id=434 data-nosnippet>434</a>    </span>}
<a href=#435 id=435 data-nosnippet>435</a>    <span class="doccomment">/// Add content format.
<a href=#436 id=436 data-nosnippet>436</a>    </span><span class="kw">pub fn </span>content_format(<span class="kw-2">mut </span><span class="self">self</span>, v: CrawlerContentFormat) -&gt; <span class="self">Self </span>{
<a href=#437 id=437 data-nosnippet>437</a>        <span class="self">self</span>.cfg.content_formats.push(v);
<a href=#438 id=438 data-nosnippet>438</a>        <span class="self">self
<a href=#439 id=439 data-nosnippet>439</a>    </span>}
<a href=#440 id=440 data-nosnippet>440</a>    <span class="doccomment">/// Set extraction rules.
<a href=#441 id=441 data-nosnippet>441</a>    </span><span class="kw">pub fn </span>extraction_rules(<span class="kw-2">mut </span><span class="self">self</span>, v: serde_json::Value) -&gt; <span class="self">Self </span>{
<a href=#442 id=442 data-nosnippet>442</a>        <span class="self">self</span>.cfg.extraction_rules = <span class="prelude-val">Some</span>(v);
<a href=#443 id=443 data-nosnippet>443</a>        <span class="self">self
<a href=#444 id=444 data-nosnippet>444</a>    </span>}
<a href=#445 id=445 data-nosnippet>445</a>    <span class="doccomment">/// Enable ASP.
<a href=#446 id=446 data-nosnippet>446</a>    </span><span class="kw">pub fn </span>asp(<span class="kw-2">mut </span><span class="self">self</span>, v: bool) -&gt; <span class="self">Self </span>{
<a href=#447 id=447 data-nosnippet>447</a>        <span class="self">self</span>.cfg.asp = v;
<a href=#448 id=448 data-nosnippet>448</a>        <span class="self">self
<a href=#449 id=449 data-nosnippet>449</a>    </span>}
<a href=#450 id=450 data-nosnippet>450</a>    <span class="doccomment">/// Set proxy pool name.
<a href=#451 id=451 data-nosnippet>451</a>    </span><span class="kw">pub fn </span>proxy_pool(<span class="kw-2">mut </span><span class="self">self</span>, v: <span class="kw">impl </span>Into&lt;String&gt;) -&gt; <span class="self">Self </span>{
<a href=#452 id=452 data-nosnippet>452</a>        <span class="self">self</span>.cfg.proxy_pool = <span class="prelude-val">Some</span>(v.into());
<a href=#453 id=453 data-nosnippet>453</a>        <span class="self">self
<a href=#454 id=454 data-nosnippet>454</a>    </span>}
<a href=#455 id=455 data-nosnippet>455</a>    <span class="doccomment">/// Set country.
<a href=#456 id=456 data-nosnippet>456</a>    </span><span class="kw">pub fn </span>country(<span class="kw-2">mut </span><span class="self">self</span>, v: <span class="kw">impl </span>Into&lt;String&gt;) -&gt; <span class="self">Self </span>{
<a href=#457 id=457 data-nosnippet>457</a>        <span class="self">self</span>.cfg.country = <span class="prelude-val">Some</span>(v.into());
<a href=#458 id=458 data-nosnippet>458</a>        <span class="self">self
<a href=#459 id=459 data-nosnippet>459</a>    </span>}
<a href=#460 id=460 data-nosnippet>460</a>    <span class="doccomment">/// Set webhook name.
<a href=#461 id=461 data-nosnippet>461</a>    </span><span class="kw">pub fn </span>webhook_name(<span class="kw-2">mut </span><span class="self">self</span>, v: <span class="kw">impl </span>Into&lt;String&gt;) -&gt; <span class="self">Self </span>{
<a href=#462 id=462 data-nosnippet>462</a>        <span class="self">self</span>.cfg.webhook_name = <span class="prelude-val">Some</span>(v.into());
<a href=#463 id=463 data-nosnippet>463</a>        <span class="self">self
<a href=#464 id=464 data-nosnippet>464</a>    </span>}
<a href=#465 id=465 data-nosnippet>465</a>    <span class="doccomment">/// Add webhook event.
<a href=#466 id=466 data-nosnippet>466</a>    </span><span class="kw">pub fn </span>webhook_event(<span class="kw-2">mut </span><span class="self">self</span>, v: CrawlerWebhookEvent) -&gt; <span class="self">Self </span>{
<a href=#467 id=467 data-nosnippet>467</a>        <span class="self">self</span>.cfg.webhook_events.push(v);
<a href=#468 id=468 data-nosnippet>468</a>        <span class="self">self
<a href=#469 id=469 data-nosnippet>469</a>    </span>}
<a href=#470 id=470 data-nosnippet>470</a>    <span class="doccomment">/// Finalize the builder.
<a href=#471 id=471 data-nosnippet>471</a>    </span><span class="kw">pub fn </span>build(<span class="self">self</span>) -&gt; <span class="prelude-ty">Result</span>&lt;CrawlerConfig, ScrapflyError&gt; {
<a href=#472 id=472 data-nosnippet>472</a>        <span class="self">self</span>.cfg.validate()<span class="question-mark">?</span>;
<a href=#473 id=473 data-nosnippet>473</a>        <span class="prelude-val">Ok</span>(<span class="self">self</span>.cfg)
<a href=#474 id=474 data-nosnippet>474</a>    }
<a href=#475 id=475 data-nosnippet>475</a>}
</code></pre></div></section></main></body></html>