Website Screenshot & URL to PDF Converter
Pricing
from $2.50 / 1,000 viewport screenshots
Website Screenshot & URL to PDF Converter
Screenshots (PNG/JPEG, viewport/full page) and PDFs of public web pages. No charge for failed captures; $0.01 start fee per default 2 GB run, $0.005 per GB RAM.
Pricing
from $2.50 / 1,000 viewport screenshots
Rating
0.0
(0)
Developer
Luxe Tasks
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
19 hours ago
Last modified
Categories
Share
Give it a list of public web page URLs and get back a PNG or JPEG screenshot (viewport or full page) or a PDF (A4, Letter and other sizes) of each page, with one result record per URL that links to the file.
Cost: from $2.50 per 1,000 viewport screenshots, plus a start fee of $0.01 per run at the default 2 GB of memory ($0.005 per GB). Failed, blocked, blank or skipped URLs have no per-result charge, but the run's start fee still applies. Full details are under Pricing below.
Try it: the input is prefilled with https://example.com/. Press Start, then open the dataset's Captures view and click the file link.
How to take a full-page screenshot or save a web page as PDF
- Paste your URLs into URLs (one per line, up to 1,000 per run).
- Pick Output format:
png,jpegorpdf. - For a whole scrolling page, switch on Full page (PNG/JPEG only). For PDFs, choose the paper size and orientation.
- Press Start. Each file goes to the run's key-value store, and each dataset record has a
linkto it. - To run it from code, use the JavaScript, Python or CLI examples in the API tab, or schedule the run in Apify.
Example input and output
{ "urls": ["https://example.com/"], "outputFormat": "png", "fullPage": false }
{ "index": 3, "url": "https://example.com/", "status": "success", "ok": true, "format": "png", "bytes": 48213,"key": "capture-0003-example.com-1a2b3c4d5e.png", "link": "https://api.apify.com/v2/key-value-stores/<id>/records/capture-0003-…","httpStatus": 200, "finalUrl": "https://example.com/", "redirects": 0, "truncated": false, "attempts": 1,"charged": true, "chargedEvents": 1, "chargeEvent": "screenshot", "pdfPages": null,"timingMs": { "total": 2140, "navigation": 610, "capture": 180 }, "blockedRequests": 0,"robots": { "checked": true, "allowed": true, "overridden": false, "attestation": null, "detail": "robots.txt HTTP 200" },"error": null }
What it does
- Opens only the URLs you list. It never follows links, crawls a site or opens popups.
- Captures one file per URL: PNG, JPEG or PDF (A4, Letter, Legal, A3, A5, Tabloid; landscape; print backgrounds).
- Full-page mode scrolls the page step by step to trigger lazy-loaded content, waits for images to load and decode, scrolls back to the top, then captures. Pages taller than
maxFullPageHeight(default 16,000 px) are cut at that height and markedtruncated: true. A full-page capture is charged as onefull-page-screenshotevent (not as ascreenshot). - Optionally waits for a CSS selector or a fixed delay, hides elements you name and injects your own CSS.
- By default hides common cookie-banner and ad-slot elements with CSS (cosmetic only, see FAQ). Turn off with
hideCookieBannersAndAds: false. - Honours robots.txt for every URL, every redirect hop, and every image, iframe, script or other resource the page loads, and identifies itself with a fixed User-Agent:
<browser UA> ScreenshotActor/0.1.0 (+https://apify.com/luxe_tasks/screenshot-pdf; honours robots.txt). - At most one retry per URL, in only these cases: a navigation timeout or a dropped/refused connection; an HTTP 429 that sends
Retry-Afterof 60 s or less (the wait is honoured); and, for a domain you own and attested withoverrideDomainStop, one retry after a 403, CAPTCHA page or 429 (see Responsible use). It never retries other HTTP errors, robots refusals, login walls,selector_not_found, or a URL that hit the hard per-URL limit (3 ×timeoutSecs+ 5 seconds, e.g. 95 s at the defaulttimeoutSecsof 30).
Input
| Field | Default | Notes |
|---|---|---|
urls | required | A list, or one string with URLs separated by whitespace or commas. example.com becomes https://example.com/. Whitespace is trimmed and duplicates are removed. Max 1,000. |
outputFormat | png | png, jpeg, pdf |
fullPage | false | Full scrollable page (PNG/JPEG); charged as full-page-screenshot |
viewportWidth / viewportHeight | 1280 / 800 | 320–3840 / 240–2000. A height above 2000 px is rejected (the run stops before any capture; the start fee still applies), not clamped: for taller output use fullPage. |
waitUntil | load | load, domcontentloaded, networkidle |
waitForSelector | – | Must become visible, otherwise selector_not_found |
delayMs | 0 | Extra wait before capture (max 30,000) |
scrollToLoadLazy | true | Scroll to trigger lazy content, wait for images |
maxFullPageHeight | 16000 | Height cap in px (1,000–30,000) |
jpegQuality | 80 | 1–100 |
pdfFormat, pdfLandscape, pdfPrintBackground | A4, false, true | PDF options |
pdfMarginMm | 0 | PDF margin on all four sides, 0–50 mm. With 0, the page's own CSS @page { margin } is used. |
pdfScale | 1 | PDF content scale, 0.1–2 (smaller fits more on each page) |
hideCookieBannersAndAds | true | Cosmetic CSS hiding of known banner/ad-slot selectors |
hideSelectors, customCss | – | Your own selectors/CSS (@import and url() are refused) |
timeoutSecs | 30 | Per-attempt navigation timeout, and the time allowed to take the screenshot/PDF (5–120). Very heavy full pages can need more than 30 s. |
maxConcurrency | 3 | 1–5 pages in parallel, in one shared browser. Each site is also limited to about one page per second. Concurrency may be reduced automatically to fit the run's memory (at the default 2 GB, up to 3 viewport or 2 full-page pages in parallel; at 1 GB, one page at a time); more memory allows more parallel pages (the start fee is charged per GB of memory above 1 GB). |
ignoreRobotsTxt + robotsOwnershipAttestation | off | Only for a domain you own or control: one domain, at most 10 URLs, with a written attestation. The attestation is stored in every result record. |
Not accepted: passwords, cookies, HTTP headers, auth tokens, sessions, proxies or a custom User-Agent. Inputs containing such fields are rejected before anything runs. URLs with user:password@ are rejected too.
Output
- Files go to the run's default key-value store, with keys like
capture-0003-example.com-1a2b3c4d5e.png. - One dataset record per URL goes to the run's default dataset:
{ "index": 3, "url": "https://example.com/", "status": "success", "ok": true, "format": "png", "bytes": 48213,"key": "capture-0003-example.com-1a2b3c4d5e.png", "link": "https://api.apify.com/v2/key-value-stores/<id>/records/capture-0003-…","httpStatus": 200, "finalUrl": "https://example.com/", "redirects": 0, "truncated": false, "attempts": 1,"charged": true, "chargedEvents": 1, "chargeEvent": "screenshot", "pdfPages": null,"timingMs": { "total": 2140, "navigation": 610, "capture": 180 }, "blockedRequests": 0,"robots": { "checked": true, "allowed": true, "overridden": false, "attestation": null, "detail": "robots.txt HTTP 200" },"error": null }
Status values: success, invalid_input, ssrf_blocked, robots_disallowed, robots_unreachable, http_error, timeout (the page did not load, or the screenshot/PDF could not be taken, within timeoutSecs; not charged, the start fee still applies), too_large, blocked_or_captcha, rate_limited, skipped_blocked, login_required, navigation_error, selector_not_found, save_failed, charge_failed (the charge could not be attempted; not charged, output deleted), budget_reached, blank_capture (the page rendered as a blank/uniform image or an empty file; not charged), partial_capture (the output file was incomplete, e.g. a PDF without its end marker; not charged), delivered_record_failed (rare: the file was saved and charged, but the full record could not be written; this short record has charged: true and the file key), internal_error (an unexpected error before anything was charged; not charged; the short record has the error message), state_save_failed (the progress marker could not be saved before charging, after 3 tries; not charged, output deleted), charge_pending_interrupted (the run restarted while this URL's charge was in progress and the file is gone; counted as charged with chargeUnconfirmed: true so it is never charged twice, and the record gives the key), resumed_skip (internal only: a restarted run skips a URL it already finished; no new record and no charge, so you will normally only see it in RUN_SUMMARY counts).
Other record fields: warnings (list of plain-language problems with a delivered file, e.g. 2 of 9 images did not load, resources refused by robots.txt or by the network-safety checks, blank sections), images ({ loaded, total }), imagesLoaded (e.g. "7/9"), robotsBlockedRequests (resources the page tried to load that robots.txt refused; they were never requested), blankSections (for blank_capture on a mostly blank page), chargeUnconfirmed (see Limitations), chargeStatus ("charge_uncertain" on a success record when the charge request failed or returned an unknown result after it was sent: the file is kept, charged is null, and the URL is never charged again; see Billing order), and for PDFs truncatedIsEstimate: true (see Limitations). url and finalUrl never include query strings (?[redacted]) or #fragments.
A RUN_SUMMARY record in the key-value store gives the counts for each status (plus charge_uncertain, the number of success records whose charge result is unknown), the number of events charged, chargeUncertain (events per name whose charge result is unknown), and skippedDomains: every registered domain the actor stopped visiting during the run, with the hostname that refused (refusingHost), the reason (403, captcha, or 429 (...)), the URL that triggered it, how many later URLs were skipped and on which hostnames. Each skipped URL's record has status: "skipped_blocked" and a skippedDomain object with the registered domain, the refusing host and the reason.
Pricing
Note: Apify's pricing table lists Actor Start at $0.005. That price is per GB of memory, so a default 2 GB run is charged a $0.01 start fee. Apify's 'Free up to 2,000 viewport screenshots' line does not include the start fee.
Pricing: $2.50 per 1,000 viewport screenshots; $8 per 1,000 full-page screenshots; $3 per 1,000 PDF pages; plus a $0.01 start fee per run at the default 2 GB of memory (charged per GB: $0.005 at 1 GB, +$0.005 per extra GB). Failed captures are not charged.
- Event
screenshot: one per delivered viewport PNG/JPEG. Eventfull-page-screenshot: one per delivered full-page PNG/JPEG (fullPage: true), charged instead ofscreenshot, never both. Eventpdf-page: one per page of a delivered PDF (fullPagedoes not apply to PDFs). - Viewport captures are limited to 3840 × 2000 px (no zoom, scale or clip options), so a viewport screenshot cannot stand in for a full page.
- No per-result charge for failures, timeouts, blocked, rate-limited, skipped or robots-refused URLs, invalid input, or anything not delivered; the per-run start fee still applies.
- Billing order: each file is saved to the key-value store and the save is confirmed before the event is charged; the dataset record (with the file link) is released only after a successful charge. If the save fails, nothing is charged (
save_failed). If your budget cannot cover the item, or the charge could not be attempted at all, the saved file is deleted again and no success record is released (budget_reached/charge_failed, withfileCleanupshowing the result of the deletion). If the charge request was sent but failed or returned an unknown result (Apify may have recorded it), the file is kept and delivered assuccesswithchargeStatus: "charge_uncertain",charged: nullandchargeUnconfirmed: true; that URL is never charged again, in the same run or after a restart. - Your max total charge for the run is respected. When the budget is used up, the actor stops capturing, marks the remaining URLs
budget_reachedand does not charge for them. - What you pay even when every URL fails: the start fee, charged through Apify's built-in
apify-actor-startevent once per GB of run memory. That start fee is $0.01 per run at the default 2 GB ($0.005 at 1 GB, up to $0.04 at 8 GB). This Actor does not pass platform usage (compute, storage, transfer) on to you, so a run where every URL fails costs only the start fee.
Acceptable use
Acceptable use. This Actor captures screenshots or PDFs of publicly accessible web pages that you choose. By running it you confirm that:
- You will submit only public URLs that you have the right or permission to capture, and you will use the output lawfully (for example archiving, QA, monitoring, research or evidence of your own pages or of public pages you are entitled to copy).
- You will not submit pages behind a login, paywall, or other access control, and the Actor does not accept passwords, cookies or session tokens.
- You will not use it to get around CAPTCHAs, rate limits, IP blocks, or any other technical measure a site uses to restrict access.
- You will comply with the target site's terms of use and robots.txt, and with all applicable law, including copyright and data-protection law (GDPR, CCPA and similar). You are the controller of any personal data in your captures.
- You will not capture, store or distribute illegal content, including child sexual abuse material, or use the Actor to harass, stalk, or profile individuals.
- You will not use captures to impersonate a site or its owner, build phishing or look-alike pages, or republish others' pages or trademarks except where you are entitled to (for example your own pages, licensed use, or lawful quotation or reporting).
- You will keep request volumes reasonable. The Actor enforces per-domain rate limits and identifies itself in its User-Agent. The Actor may refuse or skip URLs that violate these rules. Report problems through the Actor's Issues tab.
Privacy
"Captures are written only to your run's default Apify storage. The developer does not copy, view or retain them. The Actor does not analyse captures or extract faces or other personal data. PDFs keep the page's text as rendered by the browser. If your captures contain personal data, you are the controller and the developer acts only as your processor under Apify's Standard Actor Contract. Apify's retention settings apply."
Outputs stay in your Apify account until you delete them or Apify's retention period ends. Logs record only the URL, the status and timings, never page content. Query strings are redacted (?[redacted]) in logs and results (dataset url and finalUrl).
Responsible-use and robots.txt notes
- robots.txt is checked against both the
*group and ourScreenshotActortoken, and again on every redirect hop.- Resources too: every image, stylesheet, script, font, iframe and other request the page makes is checked against the robots.txt of its own host, on every redirect hop, before it is sent. A refused resource is not requested; the page is still captured without it, and the refusal is listed in
warningsandrobotsBlockedRequests. If a resource host's robots.txt is unreachable (5xx/network error), its resources are not loaded either. - A robots.txt that returns 4xx (except 429) means no restrictions; a 429 is treated as a rate limit and stops the domain; 5xx or an unreachable robots.txt means nothing is fetched.
- robots.txt 429: if it sends
Retry-Afterof 60 seconds or less, the actor waits that long and requests robots.txt again once. With noRetry-After, a longer one, or a second 429, the URL is reported asrate_limitedand every later URL on that domain is skipped (skipped_blocked); no page on that domain is requested and nothing is charged. - A 5xx or unreachable robots.txt is treated as "disallow all" (RFC 9309), with status
robots_unreachable.
- Resources too: every image, stylesheet, script, font, iframe and other request the page makes is checked against the robots.txt of its own host, on every redirect hop, before it is sent. A refused resource is not requested; the page is still captured without it, and the refusal is listed in
- Network safety: only
http/httpsare fetched.- Addresses are checked after DNS resolution, on every request and redirect hop, including images, iframes and scripts.
- Private, loopback, link-local, carrier-grade-NAT, multicast and reserved addresses are refused, as are cloud metadata endpoints (
169.254.169.254,metadata.google.internal). Those requests are blocked and counted inblockedRequests. - WebSockets are refused.
- No stealth plugins, CAPTCHA solving, proxy rotation or User-Agent rotation.
- When a site says no, the actor stops visiting that domain for the rest of the run:
- HTTP 403 or a CAPTCHA/bot-wall page: reported as
blocked_or_captcha; no retry; every later URL on that domain is skipped (skipped_blocked) without being requested. - HTTP 429: if the site sends
Retry-Afterof 60 seconds or less, the actor waits that long and retries once. With noRetry-After, a longer one, or a second 429, it is reported asrate_limitedand the domain is skipped for the rest of the run. - HTTP 404 or 5xx: only that URL fails (
http_error); the domain is not stopped. - A "domain" here is the registered domain (eTLD+1, from the Public Suffix List including its private section): a refusal from
shop.example.comstops every*.example.comURL in the run. Customer sites on shared hosts (alice.github.io,a-store.myshopify.com,x.blogspot.com,y.herokuapp.com) count as separate domains. An IP-address URL stops that exact IP (any port). - PSL updates: the list is the snapshot bundled in the exact-pinned
tldtspackage (7.4.19, published 2026-10-20 per the npm registry), so it works offline. To update:npm install --save-exact tldts@<new>, runnpm test(thedomain-scopetests cover co.uk, github.io and myshopify.com), and note the version here.
- HTTP 403 or a CAPTCHA/bot-wall page: reported as
- Runtime: Node.js 24 everywhere (G-8):
package.jsonengines>=24 <25,.nvmrc24, Docker base imageapify/actor-node-playwright-chrome:24-1.64.1(Apify base images support Node 22, 24 and 26: https://docs.apify.com/sdk/js/docs/guides/docker-images), with Playwright pinned to 1.64.1 to match the image. The unit tests also pass on Node 20.19.2 (the reviewers' box), but Node 20 is not a supported runtime for this Actor.- Requests to one domain run one at a time, in input order, so no further request is sent once a domain is stopped.
- Owners only:
overrideDomainStop(with the ownership attestation naming your registered domain; all URLs on that one registered domain, subdomains included; up to 10 URLs) keeps the domain open, but each URL still gets at most one retry: after a 403 or CAPTCHA page the retry is immediate; after a 429 the actor waits forRetry-After(capped at 60 s), or 5 seconds if the site sent none. A second refusal ends that URL (blocked_or_captcha/rate_limited) but does not stop the domain. The attestation is logged in every record.
Limitations
- Pages behind logins or paywalls are out of scope by design, and redirects into a login page end as
login_required. - Very heavy pages (large articles with many images) can take longer than 30 s to capture in full-page mode; they end as
timeout(no per-result charge; the per-run start fee still applies; earlier versions labelled thisnavigation_error). RaisetimeoutSecsfor such pages. - Very tall pages are truncated at
maxFullPageHeight. PDFs are capped at 50 pages. - Memory: the default is 2 GB. Heavy pages (large JavaScript sites, very tall full-page captures) may need 4 GB; for those, choose 4 GB when you start the run (each extra GB adds $0.005 to the start fee). For light pages, 1 GB is cheaper ($0.005 start fee) but renders one page at a time. The Actor automatically lowers concurrency to fit the run's memory (at the default 2 GB, up to 3 viewport or 2 full-page pages in parallel; at 1 GB, one page at a time), so more memory also allows more pages in parallel.
- Out of memory:
navigation_errorwith "Page crashed" or "browser has been closed", or atimeoutwith "hard per-URL limit 95s exceeded" (3 ×timeoutSecs+ 5 s; 95 s at the default 30) on a heavy page, usually means the run ran out of memory (this page or another one in progress). After "browser has been closed" the Actor relaunched the browser and continued with the remaining URLs. The affected URL was not charged (the start fee still applies). Run it again with more memory. - PDF
truncatedis an estimate: it istruewhen the PDF reached the 50-page cap; the browser does not tell us whether more pages would have followed, so a document of exactly 50 pages is also marked. UsepdfPagesfor the real page count of the delivered file (that is also what you are charged for). - PDF page setup (measured with Chrome): the paper is always
pdfFormat/pdfLandscape. A page's CSS@page { size }does not change the paper, but Chrome still applies its orientation keyword (e.g.landscape) and lays the content out in the@pagebox, centred on the sheet. A CSS@page { margin }is used whenpdfMarginMmis 0; a non-zeropdfMarginMmreplaces it.
- Out of memory:
#fragmentsare kept:https://site/app#/pricingopens the#/pricingview of hash-routed apps and jumps to anchors. The fragment never leaves the browser (it is not sent to the site) and is removed from logs and results. URLs that differ only by fragment are captured separately.- Each fetched resource is capped at 10 MB, so larger documents end as
too_large. Output files are capped at 20 MB. - Blank pages are not billed: before capturing, the actor checks a viewport image; if it is a single uniform colour (fewer than 64 pixels differ), the URL is
blank_capture, even on a tall page with content further down. For full-page images, the delivered file is also split into screen-height sections: if more than half of them are blank, the URL isblank_capture(not charged;blankSectionsgives the counts); if only some are blank, the file is delivered and charged with a warning. The 50% threshold is our choice, not a standard. Output files that are empty or structurally incomplete arepartial_capture. Pages that load but are partly missing images are still delivered: checkimagesLoadedandwarnings. - CAPTCHA detection is narrow: a page counts as a CAPTCHA/bot wall only on specific challenge markers (Cloudflare, DataDome, PerimeterX, Imperva, AWS WAF, Akamai "Access Denied" pages), or a CAPTCHA widget (reCAPTCHA, hCaptcha, Turnstile, Arkose, GeeTest) on a page whose main content (header, navigation and footer ignored) is almost empty and has no form of its own. A login page with a widget is reported as
login_required. An article that mentions CAPTCHAs (even one titled "Are you a robot?"), or a contact form with a reCAPTCHA widget, is captured normally. - Restarts don't double-charge or duplicate: before each charge the Actor writes a
pendingmarker for that URL to the run's key-value store (STATE); only then does it charge. Progress is also saved when Apify migrates or aborts the run, and whenever a domain is stopped. A restarted run never charges a URL again: a URL leftpendingis treated as already charged and delivered withcharged: trueandchargeUnconfirmed: true(if the run stopped before the charge went through, you get that screenshot free). If its file is gone, the record sayscharge_pending_interruptedwith the key. A restarted run also checks the run's dataset, so a URL that already has a record is not written again, and it does not contact a domain that an earlier attempt stopped. If the progress record cannot be saved (after 3 tries), that URL is not charged (state_save_failed), and if the final save fails the run ends with an error. A URL markedcharge_uncertainis likewise treated as charged after a restart. At worst one screenshot is free; a URL is never charged twice. - Sites that block automated browsers will show up as
blocked_or_captchaorrate_limited, and the rest of that domain's URLs in the run are skipped (skipped_blocked, not charged). The actor does not try to get around blocks, and it does not retry from another IP or with another browser identity. - A 429 with
Retry-Afterup to 60 s adds that wait to the run (one retry only). - Invalid or self-signed TLS certificates fail. There is no "ignore certificate errors" option.
- Cookie-banner hiding covers common banner selectors only. Sites with full-page consent walls will be captured as they are.
- About one page per second per site, so large batches on a single domain take longer.
FAQ
Do I pay for failed or skipped URLs? No per-result charge. Only delivered files get a per-result charge; the per-run start fee still applies. Each record has charged/chargedEvents.
Does it click "Accept" on cookie banners? No. It never clicks anything, never sets consent cookies and never blocks ad or tracking requests. With hideCookieBannersAndAds on, it only hides common banner and ad-slot elements in the rendered image with CSS. Paywalls, login walls and consent walls are not removed.
Can I pass cookies or log in? No. The actor is for public pages only.
Why was my URL skipped_blocked? Earlier in the same run, that domain answered with a 403, a CAPTCHA, or a 429 the actor could not honour. The record's skippedDomain.reason and RUN_SUMMARY.skippedDomains say which. If you own the domain, see overrideDomainStop.
Why was my URL robots_disallowed? The site's robots.txt disallows that path for automated agents. If you own or control the domain, use ignoreRobotsTxt with an ownership attestation, for up to 10 URLs on that one domain.
Why ssrf_blocked? The URL, or a redirect or resource it loads, points at a private or internal network address. The actor only captures the public internet.
Where are my files? They are in the run's default key-value store. Each dataset record has a link.
How much does it cost to screenshot 1,000 web pages? In one run at the default 2 GB of memory, 1,000 delivered viewport screenshots cost $2.50 plus the $0.01 start fee, $2.51 in total. Full-page screenshots cost $8 per 1,000 plus the same $0.01 start fee per run. Each separate run adds its own start fee.
How much does it cost to convert a URL to PDF? Each PDF page costs $0.003, plus the $0.01 start fee per run at the default 2 GB, so a single 10-page PDF in its own run costs $0.03 plus the $0.01 start fee ($0.04).
Can I convert raw HTML (not a URL) to PDF? No. The Actor opens only public http(s) URLs you list. It does not accept HTML pasted as input.
What's the difference between a viewport and a full-page screenshot? A viewport screenshot is the visible window (default 1280 × 800 px, height at most 2000 px). A full-page screenshot scrolls the whole page (up to maxFullPageHeight, default 16,000 px) and is charged as a full-page-screenshot event instead.
Can I run it on a schedule or from my own code? Yes. Use Apify schedules, or the JavaScript, Python, CLI or MCP examples in the API tab.
More tools from Luxe Tasks
Took a PNG or JPEG screenshot and need the text in the image? OCR Text Extractor reads PNG and JPEG files.
| Tool | What it does |
|---|---|
| Tech Stack Detector | Finds the CMS, JavaScript frameworks, analytics, CDN and web server a public website uses, with evidence. |
| OCR Text Extractor | Extracts English text from scanned PDFs, PNG and JPEG images with Tesseract OCR that runs inside the Actor. |
| HTTP API Request Runner | Calls APIs you are authorized to use, with your own key kept in an encrypted secret input field. |
Each tool is priced per result plus a per-run start fee; see that tool's Pricing section.
Developer: Luxe_tasks.