'How to capture network (XHR)? (Selenium 4)
How to capture network (XHR)? You can track the desired packs (XHR) in the Chrome (Open DevTools (F12) → Open tab “Network” → Select filter “Fetch/XHR”).
I found solutions where BrowserMob Proxy is used to capture traffic. But I wanted to use Selenium 4 which can work with CDP (Chrome DevTools Protocol).
I can successfully receive XHR packs (status 200). But I cannot get the body (getResponseBody) of some XHR packs.
namespace SeleniumCDP
{
using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Threading.Tasks;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.DevTools;
using DevToolsVer = OpenQA.Selenium.DevTools.V93;
class Program
{
private static IWebDriver Driver = null;
private static IDevTools Tools = null;
private static IDevToolsSession Session = null;
private static DevToolsVer.DevToolsSessionDomains Domains = null;
private static ConcurrentBag<Task<Response>> CollectionXHR = null;
public struct Response
{
public string RequestId { get; set; }
public string ResponseUrl { get; set; }
public long ResponseStatus { get; set; }
public bool ResponseBodySuccess { get; set; }
public string ResponseBody { get; set; }
}
private static async Task Main()
{
Driver = new ChromeDriver();
Driver.Manage().Timeouts().ImplicitWait = new TimeSpan(0, 0, 10);
Driver.Manage().Timeouts().AsynchronousJavaScript = new TimeSpan(0, 0, 30);
Driver.Manage().Timeouts().PageLoad = new TimeSpan(0, 0, 30);
Driver.Manage().Window.Maximize();
Tools = Driver as IDevTools;
Session = Tools.GetDevToolsSession();
Domains = Session.GetVersionSpecificDomains<DevToolsVer.DevToolsSessionDomains>();
await Domains.Network.Enable(new DevToolsVer.Network.EnableCommandSettings());
// Create storage
CollectionXHR = new ConcurrentBag<Task<Response>>();
// Enable receiving packs
Domains.Network.ResponseReceived += ResponseReceived;
// Some actions
Instagram("username", "password"); // !!!
// Disable receiving packs
Domains.Network.ResponseReceived -= ResponseReceived;
// Waiting for completion
Task.WaitAll(CollectionXHR.ToArray());
// Number of failures
var failResponseBody = CollectionXHR.Where(w => w.Result.ResponseBodySuccess == false).Count();
// Info
string log = string.Empty;
foreach (var i in CollectionXHR.Where(w => w.Result.ResponseBodySuccess == false).ToList())
{
log += $"RequestId = {i.Result.RequestId} | "; ;
log += $"ResponseStatus = {i.Result.ResponseStatus} | ";
log += $"ResponseBodySuccess = {i.Result.ResponseBodySuccess} | ";
log += $"ResponseBody = {i.Result.ResponseBody} \n";
}
}
private static void ResponseReceived(object sender, DevToolsVer.Network.ResponseReceivedEventArgs e)
{
if (e.Type == DevToolsVer.Network.ResourceType.XHR)
{
CollectionXHR.Add(GetResponseBodyAsync(e));
}
}
private static async Task<Response> GetResponseBodyAsync(DevToolsVer.Network.ResponseReceivedEventArgs e)
{
try
{
var cmd = new DevToolsVer.Network.GetResponseBodyCommandSettings();
cmd.RequestId = e.RequestId;
var data = await Domains.Network.GetResponseBody(cmd);
return new Response()
{
RequestId = e.RequestId,
ResponseUrl = e.Response.Url,
ResponseStatus = e.Response.Status,
ResponseBodySuccess = true,
ResponseBody = data.Body
};
}
catch (Exception ex)
{
return new Response()
{
RequestId = e.RequestId,
ResponseUrl = e.Response.Url,
ResponseStatus = e.Response.Status,
ResponseBodySuccess = false,
ResponseBody = $"{ex.GetType()}: {ex.Message}"
};
}
}
private static void Instagram(string username, string password)
{
// Go to Instagram
Driver.Navigate().GoToUrl("https://www.instagram.com/");
// Login
{
var byUsernameInput = By.XPath("//form[@id='loginForm']//input[@name='username']");
var byPasswordInput = By.XPath("//form[@id='loginForm']//input[@name='password']");
var byLoginButton = By.XPath("//form[@id='loginForm']//button[@type='submit']");
if (Driver.FindElements(byLoginButton).Count > 0)
{
Driver.FindElement(byUsernameInput).SendKeys(username);
Driver.FindElement(byPasswordInput).SendKeys(password);
Driver.FindElement(byLoginButton).Click();
}
}
// Go to direct
{
var byLink = By.XPath("//a[@href='/direct/inbox/']");
if (Driver.FindElements(byLink).Count > 0)
{
Driver.FindElement(byLink).Click();
}
}
}
}
}
If you run my code several times, you will find that the failResponseBody is greater than 0. Exceptions contain one of the following messages:
- Network.getResponseBody: No resource with given identifier found
- Network.getResponseBody: No data found for resource with given identifier
What am I doing wrong?
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|