Go client library for Apple's WebDriverAgent (WDA). A 1:1 Go equivalent of openatx/facebook-wda (Python).
Automate iOS devices — find elements, tap, swipe, launch apps, take screenshots, handle alerts, and more.
go get github.com/dimmkirr/gowdapackage main
import (
"context"
"fmt"
"log"
"github.com/dimmkirr/gowda"
)
func main() {
ctx := context.Background()
client := gowda.NewClient("http://localhost:8100")
// Check WDA status
status, err := client.Status(ctx)
if err != nil {
log.Fatal(err)
}
fmt.Println("WDA status:", status)
// Create a session
sess, err := client.Session(ctx, gowda.WithBundleID("com.example.app"))
if err != nil {
log.Fatal(err)
}
defer sess.Close(ctx)
// Tap at coordinates
sess.Tap(ctx, 200, 400)
// Find and click an element
sess.Select(gowda.ByName("Sign In")).Click(ctx)
// Find element and read its text
el, err := sess.Select(gowda.ByClassName("StaticText"), gowda.ByLabelContains("Welcome")).Get(ctx)
if err != nil {
log.Fatal(err)
}
text, _ := el.Text(ctx)
fmt.Println("Found:", text)
}A command-line tool is included for quick device interaction and debugging.
# Build
go build -o bin/wda ./cmd/wda
# Or with Task
task buildSet the WDA URL via environment variable or flag:
export DEVICE_URL=http://192.168.1.50:8100
# or
wda -url http://192.168.1.50:8100 statuswda status # WDA server status
wda screenshot -o screen.png # Save screenshot
wda source -format xml # Page source
wda tap 200 400 # Tap at coordinates
wda doubletap 200 400 # Double-tap
wda swipe 100 500 100 100 # Swipe
wda home # Press home
wda lock / unlock # Lock/unlock device
wda launch com.example.app # Launch app
wda terminate com.example.app # Terminate app
wda current # Current app info
wda applist # Running apps
wda appstate com.example.app # App state
wda info # Device info
wda battery # Battery info
wda orientation # Get orientation
wda orientation LANDSCAPE # Set orientation
wda window-size # Window dimensions
wda press home # Press button
wda keys "hello" # Send keystrokes
wda alert text # Read alert text
wda alert accept # Accept alert
wda alert dismiss # Dismiss alert
wda alert buttons # List alert buttons
wda alert click Allow # Click alert button
wda siri "open Settings" # Activate Siri
wda clipboard get # Read clipboard
wda clipboard set "hello" # Set clipboard
client := gowda.NewClient(url,
gowda.WithHTTPTimeout(30*time.Second),
gowda.WithHTTPClient(customHTTPClient),
)
client.Status(ctx) // WDA server status
client.IsReady(ctx) // Quick readiness check
client.WaitReady(ctx, timeout) // Wait until WDA responds
client.Home(ctx) // Press home button
client.Locked(ctx) // Check lock state
client.Lock(ctx) // Lock device
client.Unlock(ctx) // Unlock device
client.Screenshot(ctx) // PNG screenshot bytes
client.Source(ctx, "xml") // Page source
client.AppCurrent(ctx) // Current app infosess, _ := client.Session(ctx,
gowda.WithBundleID("com.example.app"),
gowda.WithArguments([]string{"-debug"}),
gowda.WithEnvironment(map[string]string{"KEY": "VAL"}),
)
defer sess.Close(ctx)
sess.AppLaunch(ctx, bundleID) // Launch app
sess.AppTerminate(ctx, bundleID) // Terminate app
sess.AppActivate(ctx, bundleID) // Bring to foreground
sess.AppState(ctx, bundleID) // App state
sess.AppList(ctx) // Running apps
sess.Tap(ctx, x, y) // Tap
sess.DoubleTap(ctx, x, y) // Double-tap
sess.TapHold(ctx, x, y, duration) // Long press
sess.Swipe(ctx, x1, y1, x2, y2, dur) // Swipe
sess.SwipeUp(ctx) // Directional swipes
sess.SendKeys(ctx, "text") // Type text
sess.Press(ctx, "home") // Press button
sess.Orientation(ctx) // Get orientation
sess.SetOrientation(ctx, val) // Set orientation
sess.WindowSize(ctx) // Window size
sess.DeviceInfo(ctx) // Device info
sess.BatteryInfo(ctx) // Battery info
sess.SetClipboard(ctx, text, "") // Set clipboard
sess.GetClipboard(ctx) // Get clipboard
sess.SiriActivate(ctx, "open X") // Siri
sess.Deactivate(ctx, duration) // Background app
sess.OpenURL(ctx, url) // Open URL
sess.Scale(ctx) // UIKit scale factor
sess.ImplicitlyWait(10*time.Second) // Default find timeoutsel := sess.Select(
gowda.ByName("Login"), // Exact name match
gowda.ByClassName("Button"), // XCUIElementType
gowda.ByLabel("Submit"), // Label match
gowda.ByLabelContains("Sub"), // Partial label
gowda.ByNameContains("Log"), // Partial name
gowda.ByNameMatches("Log.*"), // Regex name
gowda.ByValue("on"), // Value match
gowda.ByValueContains("o"), // Partial value
gowda.ByVisible(true), // Visibility
gowda.ByEnabled(true), // Enabled state
gowda.ByID("element-id"), // Raw identifier
gowda.ByXPath("//XCUIElementTypeButton"), // XPath
gowda.ByClassChain("**/Button"), // Class chain
gowda.ByPredicate("name == 'x'"),// Predicate string
gowda.WithTimeout(5*time.Second),// Find timeout
gowda.AtIndex(0), // Element index
)
el, err := sel.Get(ctx) // Wait and return first match
elements, _ := sel.FindElements(ctx) // All matches (no wait)
count, _ := sel.Count(ctx) // Count matches
exists, _ := sel.Exists(ctx) // Check existence (no wait)
sel.Click(ctx) // Wait and click
sel.ClickExists(ctx, 3*time.Second) // Click if found
sel.Wait(ctx) // Wait, nil if not found
sel.WaitGone(ctx) // Wait for disappearance
sel.Child(gowda.ByClassName("Text")) // Scoped child searchel.Label(ctx) // Label attribute
el.Text(ctx) // Text content
el.Name(ctx) // Name
el.Value(ctx) // Value attribute
el.ClassName(ctx) // Element type
el.Enabled(ctx) // Is enabled
el.Displayed(ctx) // Is displayed
el.Visible(ctx) // Is visible
el.Accessible(ctx) // Is accessible
el.AccessibilityContainer(ctx) // Is accessibility container
el.Selected(ctx) // Is selected
el.Bounds(ctx) // Bounding Rect
el.Tap(ctx) // Tap via element endpoint
el.Click(ctx) // Tap at center coordinates
el.TapHold(ctx, 2.0) // Long press (seconds)
el.SetText(ctx, "hello") // Set text
el.ClearText(ctx) // Clear text
el.Scroll(ctx, "down", 1.0) // Scroll (visible/up/down/left/right)
el.Pinch(ctx, 2.0, 1.0) // Pinch (scale, velocity)alert := sess.Alert()
alert.Exists(ctx) // Check if alert is showing
alert.Text(ctx) // Alert text
alert.SetText(ctx, "input") // Set alert text field
alert.Accept(ctx) // Accept
alert.Dismiss(ctx) // Dismiss
alert.Buttons(ctx) // List button names
alert.Click(ctx, "Allow") // Click specific button
alert.ClickAny(ctx, []string{"Allow", "OK"}) // Click first match
alert.ClickExists(ctx, buttonNames) // Click if found, "" if not
alert.Wait(ctx, 10*time.Second) // Wait for alertRequires Go 1.26+ and Task.
task build # Build library and CLI
task test # Run all tests
task lint # Run go vet
go test ./... -run TestName -v # Run a single testMIT