- Questions
-
How to get Safari browser logs on iOS?
How to get Safari browser logs on iOS?
When running automated tests on Safari for iOS devices, capturing browser logs is essential for debugging JavaScript errors, monitoring network requests, and diagnosing issues. Appium provides several log types that give you insight into what's happening inside Safari during your test sessions.
Available Safari Log Types
When testing Safari on iOS through Appium, the following log types are available:
| Log Type | Description |
|---|---|
| safariConsole | JavaScript console output from Safari, including errors, warnings and log messages |
| safariNetwork | Network request and response logs from Safari, useful for debugging API calls and resource loading |
| syslog | iOS system log messages from the device or simulator |
| crashlog | Crash reports from the device or simulator |
| performance | Performance timing data for page loads and resource fetches |
| server | Appium server log output |
Appium Capabilities for Safari Logging
To enable Safari log capture, you need to set specific Appium capabilities in your test configuration:
| Capability | Description |
|---|---|
| appium:showSafariConsoleLog | Set to true to enable capturing Safari console logs |
| appium:showSafariNetworkLog | Set to true to enable capturing Safari network logs |
JavaScript / Node.js Example
const { Builder } = require('selenium-webdriver');
(async () => {
const driver = await new Builder()
.usingServer('https://key:secret@hub.testingbot.com/wd/hub')
.withCapabilities({
browserName: 'safari',
browserVersion: '18.6',
'appium:deviceName': 'iPhone 16',
platformName: 'iOS',
'tb:name': 'Safari Log Test',
'appium:showSafariConsoleLog': true,
'appium:showSafariNetworkLog': true
})
.build();
try {
await driver.navigate().to('https://testingbot.com');
await driver.sleep(3000);
const types = await driver.manage().logs().getAvailableLogTypes();
console.log('Available log types:', types);
const consoleLogs = await driver.manage().logs().get('safariConsole');
console.log('Safari console logs:');
consoleLogs.forEach(entry => {
console.log(`[${entry.level}] ${entry.timestamp} - ${entry.message}`);
});
const networkLogs = await driver.manage().logs().get('safariNetwork');
console.log('Safari network logs:');
networkLogs.forEach(entry => {
console.log(`[${entry.level}] ${entry.message}`);
});
} finally {
await driver.quit();
}
})();
Python Example
from selenium import webdriver
import time
capabilities = {
"browserName": "safari",
"browserVersion": "18.6",
"appium:deviceName": "iPhone 16",
"platformName": "iOS",
"tb:name": "Safari Log Test",
"appium:showSafariConsoleLog": True,
"appium:showSafariNetworkLog": True
}
driver = webdriver.Remote(
command_executor="https://key:secret@hub.testingbot.com/wd/hub",
desired_capabilities=capabilities
)
try:
driver.get("https://testingbot.com")
time.sleep(3)
available_types = driver.log_types
print("Available log types:", available_types)
console_logs = driver.get_log("safariConsole")
print("Safari console logs:")
for entry in console_logs:
print(f"[{entry['level']}] {entry['timestamp']} - {entry['message']}")
network_logs = driver.get_log("safariNetwork")
print("Safari network logs:")
for entry in network_logs:
print(f"[{entry['level']}] {entry['message']}")
finally:
driver.quit()
Java Example
import org.openqa.selenium.*;
import org.openqa.selenium.remote.*;
import org.openqa.selenium.logging.*;
import java.net.URL;
import java.util.Set;
public class SafariLogTest {
public static void main(String[] args) throws Exception {
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability("browserName", "safari");
capabilities.setCapability("browserVersion", "18.6");
capabilities.setCapability("appium:deviceName", "iPhone 16");
capabilities.setCapability("platformName", "iOS");
capabilities.setCapability("tb:name", "Safari Log Test");
capabilities.setCapability("appium:showSafariConsoleLog", true);
capabilities.setCapability("appium:showSafariNetworkLog", true);
RemoteWebDriver driver = new RemoteWebDriver(
new URL("https://key:secret@hub.testingbot.com/wd/hub"),
capabilities
);
try {
driver.get("https://testingbot.com");
Thread.sleep(3000);
Set<String> logTypes = driver.manage().logs().getAvailableLogTypes();
System.out.println("Available log types: " + logTypes);
LogEntries consoleLogs = driver.manage().logs().get("safariConsole");
System.out.println("Safari console logs:");
for (LogEntry entry : consoleLogs) {
System.out.printf("[%s] %s - %s%n",
entry.getLevel(), entry.getTimestamp(), entry.getMessage());
}
LogEntries networkLogs = driver.manage().logs().get("safariNetwork");
System.out.println("Safari network logs:");
for (LogEntry entry : networkLogs) {
System.out.printf("[%s] %s%n", entry.getLevel(), entry.getMessage());
}
} finally {
driver.quit();
}
}
}
C# Example
using OpenQA.Selenium;
using OpenQA.Selenium.Remote;
var capabilities = new DesiredCapabilities();
capabilities.SetCapability("browserName", "safari");
capabilities.SetCapability("browserVersion", "18.6");
capabilities.SetCapability("appium:deviceName", "iPhone 16");
capabilities.SetCapability("platformName", "iOS");
capabilities.SetCapability("tb:name", "Safari Log Test");
capabilities.SetCapability("appium:showSafariConsoleLog", true);
capabilities.SetCapability("appium:showSafariNetworkLog", true);
var driver = new RemoteWebDriver(
new Uri("https://key:secret@hub.testingbot.com/wd/hub"),
capabilities,
TimeSpan.FromSeconds(300)
);
try
{
driver.Navigate().GoToUrl("https://testingbot.com");
Thread.Sleep(3000);
var types = driver.Manage().Logs.AvailableLogTypes;
Console.WriteLine("Available log types:");
foreach (var type in types)
{
Console.WriteLine(type);
}
var consoleLogs = driver.Manage().Logs.GetLog("safariConsole");
Console.WriteLine("Safari console logs:");
foreach (var entry in consoleLogs)
{
Console.WriteLine($"[{entry.Level}] {entry.Timestamp} - {entry.Message}");
}
var networkLogs = driver.Manage().Logs.GetLog("safariNetwork");
Console.WriteLine("Safari network logs:");
foreach (var entry in networkLogs)
{
Console.WriteLine($"[{entry.Level}] {entry.Message}");
}
}
finally
{
driver.Quit();
}
Ruby Example
require "selenium-webdriver"
caps = Selenium::WebDriver::Remote::Capabilities.new
caps["browserName"] = "safari"
caps["browserVersion"] = "18.6"
caps["appium:deviceName"] = "iPhone 16"
caps["platformName"] = "iOS"
caps["tb:name"] = "Safari Log Test"
caps["appium:showSafariConsoleLog"] = true
caps["appium:showSafariNetworkLog"] = true
http_client = Selenium::WebDriver::Remote::Http::Default.new
http_client.read_timeout = 300
http_client.open_timeout = 300
driver = Selenium::WebDriver.for(
:remote,
url: "https://key:secret@hub.testingbot.com/wd/hub",
options: caps,
http_client: http_client
)
begin
driver.navigate.to "https://testingbot.com"
sleep 3
bridge = driver.send(:bridge)
session_id = bridge.session_id
types = bridge.http.call(:get, "session/#{session_id}/se/log/types", nil)
puts "Available log types:"
puts types.inspect
logs = bridge.http.call(:post, "session/#{session_id}/se/log", { type: "safariConsole" })
puts "Safari console logs:"
logs["value"].each do |entry|
puts "[#{entry['level']}] #{entry['timestamp']} - #{entry['message']}"
end
network_logs = bridge.http.call(:post, "session/#{session_id}/se/log", { type: "safariNetwork" })
puts "Safari network logs:"
network_logs["value"].each do |entry|
puts "[#{entry['level']}] #{entry['message']}"
end
ensure
driver.quit
end
manage.logs API has been removed. The Ruby example above uses direct HTTP calls to the WebDriver log endpoints as a workaround.
Understanding Log Output
Each log entry contains the following fields:
- level: The severity level (INFO, WARNING, SEVERE)
- timestamp: Unix timestamp of when the log entry was created
- message: The log message content
safariConsole Output
Console logs capture JavaScript output including:
-
console.log(),console.warn(), andconsole.error()calls - Unhandled JavaScript exceptions
- Content Security Policy violations
- Deprecation warnings from Safari
safariNetwork Output
Network logs capture HTTP activity including:
- Request URLs, methods and headers
- Response status codes and timing
- Failed requests and timeouts
- Resource loading errors
Using Safari Logs with TestingBot
When running Safari iOS tests on TestingBot, logs are also available through the TestingBot dashboard. You can view logs for completed test sessions without needing to fetch them programmatically.
For real-time log access during test execution, use the code examples above with the appium:showSafariConsoleLog and appium:showSafariNetworkLog capabilities enabled.
Sign up for a Free Trial
Start testing your apps with TestingBot.
No credit card required.