WWW::Me...ookbook(3)
β¨ NAME β¨
WWW::Mechanize::Chrome::Cookbook β like, the whole vibe of getting things done with WWW::Mechanize::Chrome π bestie this is your recipe book, it's the Perl module docs (User Contributed Perl Documentation, to be exact π).
π Chrome versions π
Okay so first things first, you can go find all the various current Chrome builds right here: <https://chromium.woolyss.com/> π¦
And here's the recommended approach to automation, no cap: save yourself a Chrome / Chromium version and disable automatic updates so that instead you update at a defined point in time. That way you keep the change to your automation under control π . It's giving "I am the main character of my own dependency graph."
π Web Application Testing with Chrome π
π Rationale
So if you have an application with complex Javascript, you may lowkey want to do end to end tests using WWW::Mechanize::Chrome. And the iconic part? You can run your server application and your test program in the same process if your server application can be run under PSGI β which, bestie, most web frameworks do β¨.
Having all data within one process makes it very easy to fudge configuration values or database entries at just the right time. Sneaky? Maybe. Useful? Absolutely. π
π§ Initializing the web server in your test script
You will need to use a PSGI web server written in Perl that supports event loops also supported by WWW::Mechanize::Chrome. Twiggy is one such server. The setup for Twiggy is as follows:
use Twiggy::Server;
use File::Temp 'tempdir';
my $port = 5099;
my $server = Twiggy::Server->new(
host => '127.0.0.1',
port => $port,
);
# Dancer specific parts
$ENV{DANCER_APPHANDLER} = 'Dancer::Handler::PSGI';
my $handler = Dancer::Handler->get_handler();
Dancer::_load_app('App::mykeep');
my $app = $handler->psgi_app();
# Rest of Twiggy setup
$server->register_service($app);
# Fudge the config as appropriate for our test
Dancer::config()->{mykeep}->{notes_dir} = tempdir(
CLEANUP => 1,
);
my $mech = WWW::Mechanize::Chrome->new(
);
my $res = $mech->get("http://127.0.0.1:$port");
ok $res->is_success, "We can request the page";
Periodt. That's the whole setup, and yes, the empty ->new( ) call is just like that in the original, bestie, I don't make the rules π«Ά
π₯ Debugging Headless Sessions
Okay so imagine this: you wanna watch what a headless browser automation run is actually doing. Iconic question. The answer is that you can do so by sending a screencast from WWW::Mechanize::Chrome to a different browser that supports websockets β using Mojolicious::Plugin::PNGCast from within your automation session π
use Mojolicious::Lite;
use Mojo::Server::Daemon;
use WWW::Mechanize::Chrome;
plugin 'PNGCast';
my $daemon_url = 'http://localhost:3000';
my $ws_monitor = Mojo::Server::Daemon->new(app => app());
$ws_monitor->listen([$daemon_url]);
$ws_monitor->start;
my $mech = WWW::Mechanize::Chrome->new( headless => 1 );
$mech->setScreenFrameCallback( sub {
app->send_frame( $_[1]->{data} )}
);
print "Watch progress at $daemon_url\n";
sleep 5;
$mech->get('https://example.com');
# ... more automation
This will send the progress of your headless session to your browser so you can see the differences between what you expect and what the browser displays ππ the way that this saves you from "why is it broken" at 3am is unmatched.
π¦ Listing all requests made by a page
Sometimes you want to block a single class of requests, or just list what requests a page makes. This is supported since Chrome 80 or so. Slay.
$mech->target->send_message('Fetch.enable')->get;
my $request_listener = $mech->add_listener('Fetch.requestPaused', sub {
my( $info ) = @_;
my $id = $info->{params}->{requestId};
my $request = $info->{params}->{request};
if( $request->{url} =~ /\.html(\?.*)?$/ ) {
$mech->target->send_message('Fetch.continueRequest', requestId => $id, )->retain;
return;
} else{
diag "Ignored $request->{url}";
$mech->target->send_message('Fetch.failRequest', requestId => $id, errorReason => 'AddressUnreachable' );
};
});
π SEE ALSO π
- Detecting Chrome Headless <http://antoinevastel.github.io/bot%20detection/2018/01/17/detect-chrome-headless-v2.html>
- Making Chrome Headless Undetectable <https://intoli.com/blog/making-chrome-headless-undetectable/>
- Chrome Headless Detection <https://github.com/paulirish/headless-cat-n-mouse>
- How to bypass CloudFlare <https://scrapeops.io/web-scraping-playbook/how-to-bypass-cloudflare/>
π REPOSITORY π
The public repository of this module is <https://github.com/Corion/www-mechanize-chrome> β
πΈ SUPPORT πΈ
The public support forum of this module is <https://perlmonks.org/> π«Ά
π BUG TRACKER π
Please report bugs in this module via the Github bug queue at <https://github.com/Corion/WWW-Mechanize-Chrome/issues> π
β¨ AUTHOR β¨
Max Maischein "corion@cpan.org" π
π COPYRIGHT (c) π
Copyright 2010-2026 by Max Maischein "corion@cpan.org".
π LICENSE π
This module is released under the same terms as Perl itself.
and that's the whole cookbook, bestie π this doc lives in perl v5.42.2, dated 2026-06-07, and it's a WWW::Me...ookbook(3) page β go forth and automate, you absolute icon πβ¨
π¦ where this page comes from
- fedora 43: perl-WWW-Mechanize-Chrome 0.78-1.fc43 Β· GPL-1.0-or-later OR Artistic-1.0-Perl
- fedora 44: perl-WWW-Mechanize-Chrome 0.78-1.fc44 Β· GPL-1.0-or-later OR Artistic-1.0-Perl
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms