Skip to content

nshkrdotcom/playwriter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Playwriter

Playwriter

Elixir browser automation for developers who work in WSL but need visible Windows browsers

Hex.pm Documentation License


The Problem

You're developing in WSL. You need to automate a browser. But when you launch Chromium from WSL, you get a headless process or an invisible window buried in a virtual display. You can't see what's happening. You can't debug visually. You can't demo to anyone.

The Solution

Playwriter runs Playwright directly on Windows via PowerShell, controlled from your Elixir code in WSL. The browser opens on your Windows desktop where you can see it. Click buttons, fill forms, take screenshots—all visible in real-time. No server setup, no firewall rules, no network configuration.

# This browser opens on your Windows desktop - visible!
{:ok, html} = Playwriter.fetch_html("https://example.com", mode: :windows)

Quick Start

Installation

Add to your mix.exs:

def deps do
  [{:playwriter, "~> 0.1.0"}]
end

Then run setup:

mix deps.get
mix playwriter.setup

Basic Usage (Local/Headless)

# Fetch HTML from a page
{:ok, html} = Playwriter.fetch_html("https://example.com")

# Take a screenshot
{:ok, png} = Playwriter.screenshot("https://example.com")
File.write!("screenshot.png", png)

WSL to Windows (Visible Browser)

One-time setup on Windows:

# Run from WSL - installs Playwright in Windows temp directory
powershell.exe -ExecutionPolicy Bypass -File priv/scripts/start_server.ps1 -Install

Use from Elixir:

{:ok, html} = Playwriter.fetch_html("https://example.com", mode: :windows)

A browser window opens on your Windows desktop. You watch it navigate. You see the page load.

Interactive Sessions

For complex workflows, use with_browser/2:

{:ok, result} = Playwriter.with_browser([mode: :windows], fn ctx ->
  # Navigate
  :ok = Playwriter.goto(ctx, "https://example.com/login")

  # Fill form
  :ok = Playwriter.fill(ctx, "#username", "myuser")
  :ok = Playwriter.fill(ctx, "#password", "secret")

  # Click submit
  :ok = Playwriter.click(ctx, "button[type=submit]")

  # Wait and get result
  Process.sleep(1000)
  {:ok, html} = Playwriter.content(ctx)
  html
end)

The browser stays open for the entire session. You see every action happen.

Three Modes

Mode Use Case Browser Location
:local (default) CI/CD, headless scraping Same machine as Elixir
:windows WSL development, debugging, demos Windows desktop (visible)
:remote Distributed automation (advanced) Remote server
# Local mode - fast, headless
Playwriter.fetch_html(url)
Playwriter.fetch_html(url, mode: :local)

# Windows mode - visible on Windows desktop (recommended for WSL)
Playwriter.fetch_html(url, mode: :windows)

Configuration

Playwriter.fetch_html(url,
  mode: :windows,                   # :local, :windows, or :remote
  headless: false,                  # true for invisible, false to watch
  browser_type: :chromium,          # :chromium (only for :windows mode)
  timeout: 30_000                   # milliseconds
)

Architecture

┌───────────────────────────────────────────────────┐
│                     WSL                           │
│  ┌─────────────────────────────────────────────┐  │
│  │         Your Elixir Application             │  │
│  │                                             │  │
│  │  Playwriter.fetch_html(url, mode: :windows) │  │
│  └─────────────────────┬───────────────────────┘  │
│                        │ stdin/stdout              │
│                        │ (via PowerShell)          │
└────────────────────────┼──────────────────────────┘
                         │
┌────────────────────────┼─────────────────────────┐
│                        ▼           Windows       │
│  ┌────────────────────────────────────────────┐  │
│  │         Node.js + Playwright               │  │
│  └─────────────────────┬──────────────────────┘  │
│                        │                         │
│  ┌────────────────────────────────────────────┐  │
│  │              Browser Window                │  │
│  │         (Visible on your desktop)          │  │
│  └────────────────────────────────────────────┘  │
└──────────────────────────────────────────────────┘

The :windows mode bypasses WSL2's Hyper-V networking entirely by communicating via PowerShell stdin/stdout.

Documentation

When to Use Playwriter

Use Playwriter when:

  • You develop in WSL but need to see browsers on Windows
  • You're debugging web scraping and need visual feedback
  • You want to demo browser automation to stakeholders
  • You need to interact with sites that require JavaScript rendering

Use something else when:

  • You only need headless automation (use playwright_ex directly)
  • You're not in a WSL environment
  • You need maximum performance (local mode is faster)

Contributing

Issues and PRs welcome at github.com/nshkrdotcom/playwriter.

License

MIT License. See LICENSE for details.