🚀 Capture ANY website as HD screenshots, videos, or PDFs! 📸 100+ device presets (iPhone, Android, tablets). Perfect for web scraping, monitoring, testing & marketing. Export as PNG/JPEG/PDF/MP4/GIF. Fast, reliable, proxy-ready. Try FREE now!
A rebuild around one idea: every setting should describe something the actor
actually does, and nothing a run does should be able to grow without a limit.
Video and GIF are honest now
Recording length and frame rate replace the old frame controls. A clip is
now exactly Recording length × Frames per second frames and plays for
exactly the length you asked for. The previous version advertised a frame rate
it never passed to the encoder — GIFs were fixed at 10 fps and MP4s at 30 —
and fed frames in at a different rate again, so a "5 second" GIF came out at
roughly 0.6 seconds.
Scroll recordings reach the bottom of the page. The step between frames is
worked out from the real page height, so the last frame lands at the end. The
old fixed pixel step ignored the page, so short pages ended in a run of
identical footer frames and long pages never got past the first screen.
GIFs get a proper colour palette and loop. They are also scaled to at most
800 pixels wide: a 5-second 1920-wide GIF measured 10 MB, the same clip at 800
is under 2.5 MB.
Recording is roughly twice as fast, because frames are captured in a
format that a browser can produce in a third of the time and both video
encoders are lossy anyway.
Limits that hold
Scrolling always stops. There is a scrolling limit in seconds, it applies
to every run, and it is what ends the scroll on an endless feed. The old
"infinite scroll" switch had no stopping condition at all: on a real feed the
run scrolled until the platform killed it.
Every stage has a deadline — the page, the scroll, the recording, the
encoder. A stage that runs long is stopped and whatever was captured is still
delivered, instead of the run hanging.
Very tall pages are clipped, deliberately and visibly. A full-page image
is capped at 16 000 pixels, which is the tallest a browser can render in one
pass, and the result row says when clipping happened.
Fixes
0 retries used to mean zero attempts: the page was never opened and the
screenshot was of a blank tab.
PDF margins were sent to the browser as bare numbers, which it reads as
pixels. A margin set to 20 mm came out at about 5 mm. Margins now carry
their unit.
Device emulation no longer stretches recordings. The old encoder scaled every
clip to the desktop width setting, so a phone capture was stretched to 1920.
A page that fails no longer takes the run with it — each page is captured in
its own isolated browser context, and a browser that stops responding is
restarted.
The encoder is no longer invoked through a shell, so a long encode can no
longer fail after it has already succeeded.
Removed a loop that slept for one second per frame after encoding finished,
which added a minute of idle time to a 60-frame video.
New
Wait for an element before capturing, and hide elements (cookie
banners, chat bubbles) by CSS selector.
JPEG quality and landscape PDF controls.
Interrupted runs resume instead of starting over, so a restart does not
re-capture pages that were already delivered.
Every result row now carries the page title, the final address, the file size,
how long the capture took, and — when a page produced nothing — a sentence
saying what happened.
Settings from the previous version
frameCounT, frame, timefullPagE and infiniteScroll are still accepted
and are converted to the current settings; frameIntervaL, scrollSteP and
outputDir no longer have an effect. Any conversion is reported in the run log.
Every other setting keeps its name and meaning.
Target URLs are validated as addresses
The Target URLs field now checks that each line looks like a web address, so a
stray number or word is caught in the form instead of producing an empty result.
The field still takes a plain list of addresses, exactly as before — ["https://example.com"]
keeps working, and a bare domain such as example.com is completed for you. Existing
integrations need no change.
The one behaviour that changes: a list containing an entry that is not an address is now
rejected when the run is submitted, naming the position of the bad entry, rather than starting
a run that returns nothing for it.
2.0.2
Two settings that did not work at all in 2.0.
Cookies now work. Supplying cookies failed the page outright with an
internal error, so any capture of a signed-in page returned nothing.
"Verify certificates: off" now works. Turning it off had no effect, so a
page with an expired or self-signed certificate still failed to load.
Both were the same underlying cause — the actor was calling a newer browser
interface than the browser it ships with provides — and both are now written to
work on either version.
Added a test that drives a real browser and checks every single setting in the
input form actually does something, so a setting can no longer be published
without having been run at least once.
2.0.3
Cookies now work with a real browser export
A Cookie-Editor or Copy Cookies JSON export is understood exactly as it comes
out of the extension. Three of its conventions were previously dropped, any one
of which can lose the session:
expirationDate was ignored, so every cookie became a session cookie
sameSite values such as no_restriction were unrecognised and dropped
the leading dot on .example.com was stripped — that dot is what makes a
cookie apply to www.example.com
The field is now marked secret: encrypted at rest, never written to the run
log. Only the number of cookies applied is reported.
Each result row now carries cookiesSupplied and cookiesApplied, and if the
site clears your session while the page loads, the row says so instead of
quietly returning a signed-out page.
The run tells you what it is doing
Long captures used to go silent — a 300-frame recording reported nothing until
it finished, and the encoder said nothing at all, so a working run looked frozen.
Every stage now reports to the log and to the run's status line: opening the
page, page loaded, scrolling, recording n of m frames with an estimate of
the time left, building the palette, encoding, saving. Progress is reported on a
timer, so something moves every few seconds even on a slow page.
2.0.5
Files are grouped by what they are
The run's storage now shows three named collections instead of one flat list of
keys: Screenshots (PNG, JPEG), Videos & GIFs (MP4, GIF) and PDF
documents.
GIFs are filed with video rather than with the images. A GIF is a recording of
the page — same frame capture, same length and frame-rate settings as an MP4 —
even though its file type is technically an image.
File names now start with the group they belong to (screenshot-, video-,
document-). If you read files from the dataset's screenshot_url field, as
most integrations do, nothing changes.
2.0.6
"Hide elements before capturing" now catches late banners
Cookie banners are usually injected by a third-party script several seconds
after the page has finished loading — on apify.com, 8 to 10 seconds after. The
old behaviour hid whatever was on the page at one instant, which meant a banner
arriving later was still in the shot.
Hiding is now applied as a style rule the moment the page opens, so anything
matching your selectors stays hidden no matter when it appears — and the page
never shifts around as the banner mounts.
Two smaller fixes: one malformed selector no longer stops the valid ones from
working, and a selector that matches nothing is reported in the row's notes
instead of failing quietly.
The README now lists ready-made selectors for the common consent platforms.
2.0.8
Added a walkthrough screenshot to the README showing how to find a selector for
Hide elements before capturing: right-click the banner, choose Inspect, and
read the id or class off the highlighted element — # for an id, . for a
class.