Use C# To Fill Out Web Forms

I figured I’d give out a quick tip that I had to recently do in C#. A friend had asked me how to automatically fill out a web form and submit it so that he could grab the html of the results page. Luckily, it is VERY simple in C# and I assume it is just as easy in VB.NET too…


What you do is basically grab your HtmlDocument from the browser control AFTER the page has been fully loaded. From here you have some choices, if you know the ID of the elements you want and if it is not a lot of elements you can grab each element and store them into separate HtmlElement objects. If you want to fill out ALL input elements then you can use GetElementsByTagName(“input”) in place of GetElementByID(). The tag name method returns an HtmlElementCollection which you can just throw that line into a foreach loop for every HtmlElement.

Once you have your HtmlElement object that contains the correct input which you want to fill in, you can then call SetAttribute(“value”, “some value”). All you would need to do is change “some value” to whatever value you’re filling in.

Later on, you’ll need to submit the form. I’m not sure if there are various ways of going about this but I found that just by finding the submit element by its ID and invoking “click” seems to work just fine.

I realize this is not very detailed but as I write more C# examples and such I’ll get into a more detailed practice.

Author: Scyanide

Software Engineer wanting to share his experiences.

13 thoughts on “Use C# To Fill Out Web Forms”

  1. Alternatively, you can directly use HTTP. The removes the overhead of using a browser.

    A VB.Net example:

    Dim request As HttpWebRequest = WebRequest.Create([post uri])
    request.Method = "POST"
    request.Headers.Add(HttpRequestHeader.AcceptLanguage, "en-us")
    request.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip, deflate")
    request.Referer = [form uri]
    Dim postBuffer() As Byte = Encoding.GetEncoding(1252).GetBytes([form query data])
    request.ContentLength = postBuffer.Length
    Using postData As Stream = request.GetRequestStream()
    postData.Write(postBuffer, 0, postBuffer.Length)
    End Using

    Dim response As HttpWebResponse = request.GetResponse()

    Dim data As String = Nothing
    Using s As New StreamReader(response.GetResponseStream(), Encoding.GetEncoding(1252))
    data = s.ReadToEnd()
    End Using

    I would recommend using something like Fiddler to find out what exactly the HTTP headers should look like.

    1. While this does remove the overhead of the web browser control is there anything where you could combine this method with the ease of extracting a particular input element like in my example? As rule of thumb I, personally, like to follow is to be as lazy as possible or in other words use as little code possible to get work done. I’m not saying this method is long and lots of work, in fact it is fairly simple and straight forward, however I am a bit confused on 1 line. The area with [form query data], how would one format the data to fill out multiple input boxes on a web form or am I just reading this wrong?

  2. The [from query data] is where you would do it. This represents the query string of a URL (I probably should have just said [query string]) and will look something like: firstName=John&lastName=Doe.

    You can be lazier by making this into a more general function.

  3. Nice examples guys. I just recently had to create a console application that auto completed and submitted a web form.

    I could not use an application with a browser control and I wasen’t getting posted query string values. I had to call a process to launch a browser and navigate to a url, parse a specified web document to identify certain elements, insert data and submit. Here is the ‘core’ code for what I did…

    static void Main(string[] args)
    {
    LaunchIE ie = new LaunchIE();
    ie.CreateIE();
    ie.LoadDocument();
    }

    /***Create a LaunchIE class****/
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Diagnostics;
    using System.Runtime.InteropServices;
    using SHDocVw;//Reference Microsoft Internet Controls

    namespace EduLoader
    {
    class LaunchIE
    {
    private int timeout = 10000; // 10 secs.
    private SHDocVw.ShellWindows windows = null;
    private Process process = null;
    private ManualResetEvent waitForRegister = null;

    private SHDocVw.InternetExplorer IE = null;
    public object Document
    {
    get { return IE.Document; }
    }

    public void CreateIE()
    {
    // Block until the window is registered
    waitForRegister = new ManualResetEvent(false);

    // Use the shell to get notification of when our window is created and registered
    windows = new SHDocVw.ShellWindowsClass();
    //Create event handler delegate and assign the windows_WindowRegistered method
    SHDocVw.DShellWindowsEvents_WindowRegisteredEventHandler registerHandler =
    new SHDocVw.DShellWindowsEvents_WindowRegisteredEventHandler(windows_WindowRegistered);
    windows.WindowRegistered += registerHandler;

    // Launch IE
    process = Process.Start(“IExplore”, “http://www.devryu.net/”);//NOTE: Leave out iexplore if you use some other browser
    waitForRegister.WaitOne(timeout, false); // We block here for at max 10 secs

    // Remove event
    windows.WindowRegistered -= registerHandler;
    // Flush. You could get an error here if windows_WindowRegistered is still processing
    // You could increase the timeout or just make sure its completed before releasing
    while (Marshal.ReleaseComObject(windows) > 0) ; // make sure we drop everything
    waitForRegister = null;

    //IE should be an object
    if (IE == null)
    throw new Exception(“Timeout while creating an IE Window”);

    }

    private void windows_WindowRegistered(int lCookie)
    {
    if (process == null)
    return; // Should have launched our browser with url.

    //Loop over shell windows
    for (int i = 0; i < windows.Count; i++)
    {
    //Get window. Should probably check object type here before cast
    SHDocVw.InternetExplorer ShellWindow = windows.Item(i) as SHDocVw.InternetExplorer;

    //Check object is not null and compare IntPtr handles. Should check for IntPtr = 0
    //before casting. This could happen if the window did not have time to load.
    //Also, MainWindowHandle may not be the best way to check since it may not be the top most
    //and your window may have a IntPtr of 0
    if (ShellWindow != null && (IntPtr)ShellWindow.HWND == process.MainWindowHandle)
    {
    //Assign the actuall shellwindow browser instance to your IE object instance
    IE = ShellWindow;
    // Signal the constructor that it is safe to go on now.
    waitForRegister.Set();

    return;
    }
    }
    }
    ///
    /// Load the doc, get the elements, complete the forms values and submit
    ///
    public void LoadDocument()
    {
    //Reference to “Microsoft HTML Object Library”
    mshtml.IHTMLDocument3 document = null;
    int maxwait = 10000;
    try
    {
    //Make sure it is loaded and ready
    for(int count=0;count < maxwait;count++)
    {
    if(IE.ReadyState == SHDocVw.tagREADYSTATE.READYSTATE_COMPLETE)
    break;
    }

    if (IE.ReadyState == SHDocVw.tagREADYSTATE.READYSTATE_COMPLETE)
    {
    //Get the document
    document = IE.Document as mshtml.IHTMLDocument3;

    //I'm getting elements by tagname input
    mshtml.IHTMLElementCollection colHTML = document.getElementsByTagName("input");

    //Loop over them to find the ones you want
    //This is not pretty here because I just did this
    //so it will keep the code together and simple
    //Ideally, you want to get you filter criteria from
    //a config or database etc…You might also use
    //an interface that defines what you need
    foreach (mshtml.HTMLInputElement el in colHTML)
    {
    //Example gets an input element with name=username
    if ((el.type == "text") && (el.name == "username"))
    {
    el.value = "[Place your value here..]";
    }
    //Example no id or name provided in the input element
    //getting it by type
    if (el.type == "password")
    {
    el.value = "[Place your value here..]";
    }
    //Create button and click to submit
    if (el.type == "submit")
    {
    mshtml.HTMLInputElement btnSubmit = el;
    btnSubmit.click();
    }

    }

    }
    else
    throw new Exception("Timeout waiting for form object to load.");
    }
    catch
    {
    //Do something
    }
    }
    }
    }

    1. Wow, first off thanks for joining the site! =D …I’ll have more content in the near future, I promise. lol

      Second, I was looking over your example and I really like this approach. I’ll admit, I was not aware of SHDocVw but I’ll be looking into it more. Thank you!

      I always enjoy looking at other people’s approaches on solving issues because more often than not their approaches are different and gives me a different perspective on how to look at issues.

  4. thank you very much…. ,it’s really amazing ,, & I wont to do the same thing but without opening web browser… if some one can help with that. I really appreciate it.I’m kind of stuck!!

  5. Hi,

    The article is quite interesting. I was wondering if we can use similar approach to fill out a web form in other browsers eg. Google’s Chrome browser. If yes please share an example how we can achieve this with Chrome.

    Regards,
    Pankaj Kumar

  6. Great examples, But i have seen if we use webbrowser control to navigate a page then it is used to take time to load the page. What could be the best way to navigate into a page?

    1. The first comment by wiegraff13 on this page should be what you are looking for. You’ll have to translate it into C# but that shouldn’t be an issue. It’ll remove the overhead of the web browser control.

Leave a Reply