Skip to content

n7on/pup

Repository files navigation

Pup

CI PowerShell Gallery Version PowerShell Gallery Downloads License Platform

A PowerShell module for browser automation using the Chrome DevTools Protocol. Built on PuppeteerSharp, it works with PowerShell 5.1+ on Windows, Linux, and macOS.

Install

Install-Module Pup
Install-PupBrowser

Commands

Browser

Page

Frames

Permissions

Elements

Recording

Screenshots & Export

Cookies & Storage

Network

WebSocket

Session

Input

Event Handlers

Console & Debugging

Examples

Web Scraping

This example scrapes Ubuntu security notices from https://ubuntu.com/security/notices and returns the date and link to security issues.

Start browser

Import-Module Pup
$page = start-PupBrowser | New-PupPage -Url https://ubuntu.com/security/notices 

Get selectors

List selector

If you look at the opened page in the browser, you see that there are 10 notices per page. So we need a list that contains all those, so that we can iterate over it. Copy the first link name, which at this time is USN-8015-3: Linux kernel (FIPS) vulnerabilities.

# Try with different depths, and try to go as deep as possible while at the same time catching all 10 items.
$page | find-pupelements -Text "USN-8015-3: Linux kernel (FIPS) vulnerabilities" | get-PupElementPattern -Depth 3

# Type          Selector                   MatchCount Description
# ----          --------                   ---------- -----------
# ByClass       section.p-section--shallow         10 Elements with same tag and…
# ByParentClass .col-9 section                     10 All section inside .col-9
# ByAncestorId  #notices-list section              10 All section under #notices…
# ByStructure   div.col-9 section                  10 Elements in repeating div.…
# ByTag         section                            16 All section elements

$listSelector = "#notices-list section"
Date selector

If we first get the first element by using the $listSelector, we can get the element that holds the date-text, and see its selector.

$page | find-pupelements -Selector $listSelector -First | Find-PupElements -TextContains "6 february"

# Selector  : div.row > div.col-6 > p.u-text--muted
# Index     : 0
# FoundTime : 2026-02-09 20:21:09
# TagName   : P
# InnerText : 6 February 2026
# InnerHTML : 6 February 2026
# Id        : 
# IsVisible : False

$dateSelector = "div.row > div.col-6 > p.u-text--muted"
Link selector

We use the $listSelector again, and get the element that holds the link-text, and see its selector.

$page | find-pupelements -Selector $listSelector -First | Find-PupElements -TextContains "USN-8015-3: Linux kernel (FIPS) vulnerabilities"

# ElementId : 17fa5859-2293-4913-87db-4fc0049e3f89
# Selector  : div.u-fixed-width > h3.u-no-margin > a
# Index     : 0
# FoundTime : 2026-02-09 20:34:23
# TagName   : A
# InnerText : USN-8015-3: Linux kernel (FIPS) vulnerabilities
# InnerHTML : USN-8015-3: Linux kernel (FIPS) vulnerabilities
# Id        : 
# IsVisible : False

$linkSelector = "div.u-fixed-width > h3.u-no-margin > a"
NextPage selector

We need the selector to next page in order to scrape multiple pages.

# it doesn't show on the page, but if you look in source it's actually "Next page". 
# the selector from Find-PupElements doesn't look great, but if we run the element through Get-PupElementPattern we get better ones. We can choose any with 1 match.
$page | find-pupelements -Text "Next page" | Get-PupElementPattern

# Type          Selector                            MatchCount Description
# ----          --------                            ---------- -----------
# ByClass       i.p-icon--chevron-down                       3 Elements with same tag and classes
# ByTag         i                                           13 All i elements
# ByParentClass .p-pagination__link--next i                  1 All i inside .p-pagination__link--next
# ByAncestorId  #notices-list div > ol > li > a > i          1 All i under #notices-list
# ByStructure   li.p-pagination__item a > i                  1 Elements in repeating li.p-pagination__item containers

$nextPageSelector = ".p-pagination__link--next i"

Create script

Now we have everything that is needed for the script. We only need the Ubuntu notices from the last month, so we'll stop when we get an older notice.

$url = "https://ubuntu.com"
$listSelector = "#notices-list section"
$dateSelector = "div.row > div.col-6 > p.u-text--muted"
$linkSelector = "div.u-fixed-width > h3.u-no-margin > a"
$nextPageSelector = ".p-pagination__link--next i"

# check notices from 1 month back.
$fromDate = (Get-Date).AddMonths(-1)
$browser = Start-PupBrowser -Headless
$page = New-PupPage -Url "$url/security/notices"

$date = Get-Date

# while found date is not older than 1 month
while ($date -gt $fromDate) {

    $page | Find-PupElements -WaitForLoad -Selector $listSelector | ForEach-Object {
        $date = [datetime]($_ | Find-PupElements -Selector $dateSelector).InnerHTML.Trim()
        $href = $_ | Find-PupElements -Selector $linkSelector | Get-PupElementAttribute -Name href
        [PSCustomObject]@{
            Date  = $date
            Link  = "$url$href"
        }
    }
    # click next-page link
    $page | Find-PupElements -Selector $nextPageSelector | Invoke-PupElementClick
}
$browser | Stop-PupBrowser

See more examples in ./examples

Contributing

See CONTRIBUTING.md for development setup, testing, and troubleshooting.