Table of contents

How can I simulate different network conditions with Puppeteer-Sharp?

Simulating different network conditions is essential for testing web applications under various connectivity scenarios. Puppeteer-Sharp provides powerful network emulation capabilities that allow developers to simulate slow connections, high latency, and offline conditions to ensure their applications perform well across different network environments.

Understanding Network Emulation in Puppeteer-Sharp

Network emulation in Puppeteer-Sharp leverages the Chrome DevTools Protocol to modify network behavior at the browser level. This allows you to test how your web application behaves under different network conditions without actually changing your internet connection.

Setting Up Network Emulation

Basic Network Throttling

The primary method for simulating network conditions is through the Page.EmulateNetworkConditionsAsync() method:

using PuppeteerSharp;

var launchOptions = new LaunchOptions
{
    Headless = false,
    Args = new[] { "--disable-web-security", "--disable-features=VizDisplayCompositor" }
};

using var browser = await Puppeteer.LaunchAsync(launchOptions);
using var page = await browser.NewPageAsync();

// Simulate slow 3G network conditions
await page.EmulateNetworkConditionsAsync(new NetworkConditions
{
    Offline = false,
    DownloadThroughput = 1.5 * 1024 * 1024 / 8, // 1.5 Mbps in bytes per second
    UploadThroughput = 750 * 1024 / 8,          // 750 Kbps in bytes per second
    Latency = 40                                 // 40ms latency
});

await page.GoToAsync("https://example.com");

Predefined Network Profiles

You can create predefined network profiles for common scenarios:

public static class NetworkProfiles
{
    public static NetworkConditions Slow3G => new()
    {
        Offline = false,
        DownloadThroughput = 500 * 1024 / 8,   // 500 Kbps
        UploadThroughput = 500 * 1024 / 8,     // 500 Kbps
        Latency = 2000                          // 2000ms latency
    };

    public static NetworkConditions Fast3G => new()
    {
        Offline = false,
        DownloadThroughput = 1.6 * 1024 * 1024 / 8,  // 1.6 Mbps
        UploadThroughput = 750 * 1024 / 8,            // 750 Kbps
        Latency = 150                                  // 150ms latency
    };

    public static NetworkConditions Regular4G => new()
    {
        Offline = false,
        DownloadThroughput = 4 * 1024 * 1024 / 8,     // 4 Mbps
        UploadThroughput = 3 * 1024 * 1024 / 8,       // 3 Mbps
        Latency = 20                                   // 20ms latency
    };

    public static NetworkConditions Offline => new()
    {
        Offline = true,
        DownloadThroughput = 0,
        UploadThroughput = 0,
        Latency = 0
    };
}

// Usage example
await page.EmulateNetworkConditionsAsync(NetworkProfiles.Slow3G);

Advanced Network Simulation Scenarios

Testing Progressive Loading

Simulate how your application handles progressive loading under different network conditions:

public async Task TestProgressiveLoadingAsync()
{
    using var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = false });
    using var page = await browser.NewPageAsync();

    // Start with fast connection
    await page.EmulateNetworkConditionsAsync(NetworkProfiles.Fast3G);

    // Navigate and measure initial load
    var stopwatch = Stopwatch.StartNew();
    await page.GoToAsync("https://example.com");
    var initialLoadTime = stopwatch.ElapsedMilliseconds;

    Console.WriteLine($"Initial load time (Fast 3G): {initialLoadTime}ms");

    // Switch to slow connection and test subsequent interactions
    await page.EmulateNetworkConditionsAsync(NetworkProfiles.Slow3G);

    stopwatch.Restart();
    await page.ClickAsync("#load-more-content");
    await page.WaitForSelectorAsync(".new-content", new WaitForSelectorOptions 
    { 
        Timeout = 30000 
    });
    var slowLoadTime = stopwatch.ElapsedMilliseconds;

    Console.WriteLine($"Content load time (Slow 3G): {slowLoadTime}ms");
}

Simulating Intermittent Connectivity

Test how your application handles network interruptions:

public async Task TestIntermittentConnectivityAsync()
{
    using var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = false });
    using var page = await browser.NewPageAsync();

    await page.GoToAsync("https://example.com");

    // Simulate network interruption
    await page.EmulateNetworkConditionsAsync(NetworkProfiles.Offline);

    // Try to perform an action that requires network
    try
    {
        await page.ClickAsync("#submit-form");
        await page.WaitForSelectorAsync(".success-message", 
            new WaitForSelectorOptions { Timeout = 5000 });
    }
    catch (WaitTaskTimeoutException)
    {
        Console.WriteLine("Action failed due to network interruption - as expected");
    }

    // Restore connectivity
    await page.EmulateNetworkConditionsAsync(NetworkProfiles.Fast3G);

    // Retry the action
    await page.ClickAsync("#retry-button");
    await page.WaitForSelectorAsync(".success-message");
    Console.WriteLine("Action succeeded after connectivity restored");
}

Monitoring Network Performance

When tracking network requests similar to monitoring network requests in Puppeteer, you can combine network emulation with request monitoring to analyze performance:

public async Task MonitorNetworkPerformanceAsync()
{
    using var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = false });
    using var page = await browser.NewPageAsync();

    var networkRequests = new List<Request>();
    var networkResponses = new List<Response>();

    page.Request += (sender, e) => networkRequests.Add(e.Request);
    page.Response += (sender, e) => networkResponses.Add(e.Response);

    // Test under different network conditions
    var conditions = new[] 
    {
        ("Fast 3G", NetworkProfiles.Fast3G),
        ("Slow 3G", NetworkProfiles.Slow3G),
        ("Regular 4G", NetworkProfiles.Regular4G)
    };

    foreach (var (name, condition) in conditions)
    {
        await page.EmulateNetworkConditionsAsync(condition);

        var stopwatch = Stopwatch.StartNew();
        await page.ReloadAsync();
        await page.WaitForLoadStateAsync(LoadState.NetworkIdle);
        stopwatch.Stop();

        Console.WriteLine($"{name}: {stopwatch.ElapsedMilliseconds}ms, " +
                         $"Requests: {networkRequests.Count}, " +
                         $"Failed: {networkResponses.Count(r => !r.Ok)}");

        networkRequests.Clear();
        networkResponses.Clear();
    }
}

Testing Mobile Network Conditions

Combine network emulation with mobile device emulation for comprehensive mobile testing:

public async Task TestMobileNetworkConditionsAsync()
{
    using var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = false });
    using var page = await browser.NewPageAsync();

    // Emulate mobile device
    await page.EmulateAsync(new Device
    {
        Name = "iPhone 12",
        UserAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1",
        Viewport = new ViewPortOptions
        {
            Width = 390,
            Height = 844,
            DeviceScaleFactor = 3,
            IsMobile = true,
            HasTouch = true
        }
    });

    // Apply mobile network conditions
    await page.EmulateNetworkConditionsAsync(new NetworkConditions
    {
        Offline = false,
        DownloadThroughput = 1.6 * 1024 * 1024 / 8,  // Typical 3G speed
        UploadThroughput = 750 * 1024 / 8,
        Latency = 300                                  // Higher latency for mobile
    });

    await page.GoToAsync("https://example.com");

    // Test mobile-specific interactions
    await page.TapAsync("#mobile-menu-button");
    await page.WaitForSelectorAsync(".mobile-menu");
}

Network Condition Testing with Custom Profiles

Creating Custom Network Profiles

Create profiles that match real-world conditions more accurately:

public static class CustomNetworkProfiles
{
    // Based on real-world measurements
    public static NetworkConditions SlowWiFi => new()
    {
        Offline = false,
        DownloadThroughput = 2 * 1024 * 1024 / 8,     // 2 Mbps
        UploadThroughput = 1 * 1024 * 1024 / 8,       // 1 Mbps
        Latency = 100                                  // 100ms latency
    };

    public static NetworkConditions SatelliteInternet => new()
    {
        Offline = false,
        DownloadThroughput = 10 * 1024 * 1024 / 8,    // 10 Mbps
        UploadThroughput = 1 * 1024 * 1024 / 8,       // 1 Mbps
        Latency = 600                                  // 600ms latency (high satellite delay)
    };

    public static NetworkConditions Edge => new()
    {
        Offline = false,
        DownloadThroughput = 240 * 1024 / 8,          // 240 Kbps
        UploadThroughput = 200 * 1024 / 8,            // 200 Kbps
        Latency = 840                                  // 840ms latency
    };
}

Testing Multiple Scenarios Sequentially

Run comprehensive network condition tests:

public async Task TestMultipleNetworkScenariosAsync()
{
    var networkScenarios = new Dictionary<string, NetworkConditions>
    {
        { "Offline", NetworkProfiles.Offline },
        { "EDGE (2G)", CustomNetworkProfiles.Edge },
        { "Slow 3G", NetworkProfiles.Slow3G },
        { "Fast 3G", NetworkProfiles.Fast3G },
        { "4G", NetworkProfiles.Regular4G },
        { "Slow WiFi", CustomNetworkProfiles.SlowWiFi },
        { "Satellite", CustomNetworkProfiles.SatelliteInternet }
    };

    using var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = true });
    using var page = await browser.NewPageAsync();

    var results = new Dictionary<string, TimeSpan>();

    foreach (var scenario in networkScenarios)
    {
        Console.WriteLine($"Testing {scenario.Key}...");

        await page.EmulateNetworkConditionsAsync(scenario.Value);

        if (scenario.Value.Offline)
        {
            // Test offline functionality
            results[scenario.Key] = await TestOfflineScenario(page);
        }
        else
        {
            // Test online functionality with network conditions
            results[scenario.Key] = await TestOnlineScenario(page);
        }
    }

    // Print results
    foreach (var result in results)
    {
        Console.WriteLine($"{result.Key}: {result.Value.TotalMilliseconds:F2}ms");
    }
}

private async Task<TimeSpan> TestOnlineScenario(Page page)
{
    var stopwatch = Stopwatch.StartNew();

    try
    {
        await page.GoToAsync("https://httpbin.org/delay/1", new NavigationOptions 
        { 
            Timeout = 60000 
        });
        await page.WaitForSelectorAsync("body");
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Online test failed: {ex.Message}");
    }

    stopwatch.Stop();
    return stopwatch.Elapsed;
}

private async Task<TimeSpan> TestOfflineScenario(Page page)
{
    var stopwatch = Stopwatch.StartNew();

    try
    {
        // Test offline functionality - should fail quickly
        await page.GoToAsync("https://httpbin.org/delay/1", new NavigationOptions 
        { 
            Timeout = 5000 
        });
    }
    catch (Exception)
    {
        // Expected to fail in offline mode
    }

    stopwatch.Stop();
    return stopwatch.Elapsed;
}

Handling Network Emulation Edge Cases

Resetting Network Conditions

Always reset network conditions when switching between tests:

public async Task ResetNetworkConditionsAsync(Page page)
{
    // Reset to normal network conditions
    await page.EmulateNetworkConditionsAsync(new NetworkConditions
    {
        Offline = false,
        DownloadThroughput = 0,  // 0 means no throttling
        UploadThroughput = 0,    // 0 means no throttling
        Latency = 0              // 0 means no additional latency
    });
}

Handling Timeout Issues

When testing under slow network conditions, you may need to adjust timeouts accordingly, similar to handling timeouts in Puppeteer:

public async Task HandleSlowNetworkTimeoutsAsync()
{
    using var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = false });
    using var page = await browser.NewPageAsync();

    // Set longer default timeout for slow network conditions
    page.DefaultTimeout = 60000; // 60 seconds

    await page.EmulateNetworkConditionsAsync(NetworkProfiles.Slow3G);

    try
    {
        await page.GoToAsync("https://example.com", new NavigationOptions 
        { 
            Timeout = 90000  // 90 seconds for navigation
        });

        await page.WaitForSelectorAsync(".main-content", new WaitForSelectorOptions 
        { 
            Timeout = 45000  // 45 seconds for content to appear
        });
    }
    catch (TimeoutException ex)
    {
        Console.WriteLine($"Timeout occurred under slow network conditions: {ex.Message}");
    }
}

Best Practices for Network Emulation Testing

1. Test Multiple Scenarios

Create comprehensive test suites that cover various network conditions:

[TestMethod]
public async Task TestApplicationUnderVariousNetworkConditions()
{
    var testScenarios = new[]
    {
        ("Offline", NetworkProfiles.Offline),
        ("Slow 3G", NetworkProfiles.Slow3G),
        ("Fast 3G", NetworkProfiles.Fast3G),
        ("4G", NetworkProfiles.Regular4G)
    };

    foreach (var (scenarioName, networkCondition) in testScenarios)
    {
        await RunNetworkScenarioTest(scenarioName, networkCondition);
    }
}

private async Task RunNetworkScenarioTest(string scenarioName, NetworkConditions condition)
{
    using var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = true });
    using var page = await browser.NewPageAsync();

    await page.EmulateNetworkConditionsAsync(condition);

    try
    {
        if (condition.Offline)
        {
            // Test offline behavior
            await TestOfflineFunctionality(page);
        }
        else
        {
            // Test online functionality under specific network conditions
            await TestOnlineFunctionality(page, scenarioName);
        }

        Console.WriteLine($"✓ {scenarioName} test passed");
    }
    catch (Exception ex)
    {
        Console.WriteLine($"✗ {scenarioName} test failed: {ex.Message}");
    }
}

2. Measure and Log Performance Metrics

Track performance metrics across different network conditions:

public async Task MeasurePerformanceMetrics(Page page)
{
    var performanceMetrics = await page.EvaluateExpressionAsync<dynamic>(@"
        JSON.stringify({
            loadTime: performance.timing.loadEventEnd - performance.timing.navigationStart,
            domContentLoaded: performance.timing.domContentLoadedEventEnd - performance.timing.navigationStart,
            firstPaint: performance.getEntriesByType('paint')[0]?.startTime || 0,
            resourceCount: performance.getEntriesByType('resource').length
        })
    ");

    var metrics = JsonConvert.DeserializeObject(performanceMetrics.ToString());
    Console.WriteLine($"Performance Metrics: {metrics}");
}

3. Combine with Request Interception

For more advanced testing, combine network emulation with request interception:

public async Task TestWithRequestInterceptionAsync()
{
    using var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = false });
    using var page = await browser.NewPageAsync();

    // Enable request interception
    await page.SetRequestInterceptionAsync(true);

    page.Request += async (sender, e) =>
    {
        // Simulate additional delays for specific resources
        if (e.Request.Url.Contains("slow-resource"))
        {
            await Task.Delay(2000); // Additional 2-second delay
        }

        await e.Request.ContinueAsync();
    };

    // Apply network conditions
    await page.EmulateNetworkConditionsAsync(NetworkProfiles.Slow3G);

    await page.GoToAsync("https://example.com");
}

Network emulation with Puppeteer-Sharp is a powerful testing technique that helps ensure your web applications provide optimal user experiences across different connectivity scenarios. By simulating various network conditions, you can identify performance bottlenecks, test offline functionality, and optimize your application's behavior for users with limited bandwidth or intermittent connectivity.

Remember to combine network emulation with other Puppeteer-Sharp features like device emulation and performance monitoring to create comprehensive testing scenarios that reflect real-world usage patterns. This approach helps build more resilient and user-friendly web applications that work well regardless of network conditions.

Try WebScraping.AI for Your Web Scraping Needs

Looking for a powerful web scraping solution? WebScraping.AI provides an LLM-powered API that combines Chromium JavaScript rendering with rotating proxies for reliable data extraction.

Key Features:

  • AI-powered extraction: Ask questions about web pages or extract structured data fields
  • JavaScript rendering: Full Chromium browser support for dynamic content
  • Rotating proxies: Datacenter and residential proxies from multiple countries
  • Easy integration: Simple REST API with SDKs for Python, Ruby, PHP, and more
  • Reliable & scalable: Built for developers who need consistent results

Getting Started:

Get page content with AI analysis:

curl "https://api.webscraping.ai/ai/question?url=https://example.com&question=What is the main topic?&api_key=YOUR_API_KEY"

Extract structured data:

curl "https://api.webscraping.ai/ai/fields?url=https://example.com&fields[title]=Page title&fields[price]=Product price&api_key=YOUR_API_KEY"

Try in request builder

Related Questions

Get Started Now

WebScraping.AI provides rotating proxies, Chromium rendering and built-in HTML parser for web scraping
Icon