Search code examples
c#azureazure-functionsplaywright

Use Playwright in an Azure Functions Timer Trigger C#


I am using Playwright in an Azure Function Timer Trigger, developed in C#. When I debug it with Visual Studio everything works fine. I have published it in Azure, with these configurations: azure function configuration

When timer trigger runs I have these error:

Executable doesn't exist at C:\local\LocalAppData\ms-playwright\chromium-1084\chrome-win\chrome.exe ╔════════════════════════════════════════════════════════════╗ ║ Looks like Playwright was just installed or updated. ║ ║ Please run the following command to download new browsers: ║ ║ ║ ║ pwsh bin/Debug/netX/playwright.ps1 install ║ ║ ║ ║ <3 Playwright Team ║ ╚════════════════════════════════════════════════════════════╝

Did I miss some configuration on Azure?


Solution

  • I managed to install Playwright in a Windows-hosted Azure Function.

    Playwright provides a set of browser automation tools that enable developers to interact with web pages programmatically. Using it in a Windows-hosted Azure Function can be challenging. With the help of the official documentation and suggestions we have found in various blogs, we managed to use it correctly in an Azure Function. Here are the steps to follow for an Azure Function developed in C#, .NET6, in Visual Studio:

    1. Install Playwright and develop the project. In my project, I usually use Chromium as Playwright browser extension.
    2. If you try to run the project, you probably have this message: Microsoft.Playwright.PlaywrightException: Driver not found .... According to Maurice Peters blog, this is due to the fact that the output folder structure of an Azure Function is different from most projects. To fix this, you can add these targets to the csproj file, so you will copy Playwright files to an extra folder.

    <!--For the build scenario:-->
        <Target Name="FixPlaywrightCopyAfterBuild" AfterTargets="Build">
            <ItemGroup>
              <_BuildCopyItems Include="$(OutDir).playwright\**" />
            </ItemGroup>
            <Message Text="[Fix] Copying files to the nested bin folder of the azure function... $(OutDir)bin" Importance="high"/>
            <Copy SourceFiles="@(_BuildCopyItems)" DestinationFiles="@(_BuildCopyItems->'$(OutDir)bin\.playwright\%(RecursiveDir)%(Filename)%(Extension)')"/>
        </Target>
        
        <!--For the publish scenario:-->
        <Target Name="FixPlaywrightCopyAfterPublish" AfterTargets="Publish">
            <ItemGroup>
              <_BuildCopyItems Include="$(PublishDir).playwright\**" />
            </ItemGroup>
            <Message Text="[Fix] Copying files to the nested bin folder of the azure function for publishing... $(PublishDir)bin" Importance="high"/>
            <Copy SourceFiles="@(_BuildCopyItems)" DestinationFiles="@(_BuildCopyItems->'$(PublishDir)bin\.playwright\%(RecursiveDir)%(Filename)%(Extension)')"/>
        </Target>

    1. If you publish and run the function on Azure, after these steps, you may encounter the following exception:

    Executable doesn't exist at C:\home\site\wwwroot\bin\ms-playwright\chromium-1084\chrome-win\chrome.exe 
        ╔════════════════════════════════════════════════════════════╗ 
        ║ Looks like Playwright was just installed or updated.       ║ 
        ║ Please run the following command to download new browsers: ║ 
        ║                                                            ║ 
        ║ pwsh bin/Debug/netX/playwright.ps1 install                 ║
        ║                                                            ║  
        ║ <3 Playwright Team                                         ║ 
        ╚════════════════════════════════════════════════════════════╝

    According to some articles, to run Playwright in a Windows-hosted Azure Function you have to make sure the browser is executed from the HOME_EXPANDED path instead of the default HOME environment variable path. Playwright downloads Chromium, WebKit and Firefox browsers into the OS-specific cache folders, but you can ovverride the location definining the PLAYWRIGHT_BROWSERS_PATH environment variable. Now you can download Playwright browser binaries and set PLAYWRIGHT_BROWSERS_PATH in the HOME_EXPANDED directory.
    To do this, you need to overwrite the Azure Function Startup file as follows:

    using Microsoft.Azure.Functions.Extensions.DependencyInjection;
    using Microsoft.Extensions.DependencyInjection;
    using System;
    
    [assembly: FunctionsStartup(typeof(<PROJECTNAME>.Startup))]
    
        namespace <NAMESPACE>
        {
            public class Startup : FunctionsStartup
            {
                public override void Configure(IFunctionsHostBuilder builder)
                {
                    .....
                    Environment.SetEnvironmentVariable("PLAYWRIGHT_BROWSERS_PATH", Environment.GetEnvironmentVariable("HOME_EXPANDED"));
                    Microsoft.Playwright.Program.Main(new string[] { "install", "chromium", "--with-deps", });
                    .....
                }
            }
        }   

    1. Now you are ready to publish and run the Azure Function