ZFBrowser Documentation

ZFBrowser Documentation

This asset allows you to embed a full copy of Chromium, the open-source core of Google Chrome, inside your game!

Product Page | Unity Asset Store | Changelog | Get Help

Documentation for ZFBrowser v3.1.0.

Uses CEF 74.1.19+gb62bacf+chromium-74.0.3729.157 / Chromium 74.0.3729.157.

Copyright © 2015-2019 Zen Fulcrum LLC

Quick Start

Basic Browser:

Embedded assets:

Congratulations! You now have a browser in your game!

See this section if you want to use the browser in VR.


Important Note

This library is made possible by a number of third-party open source software projects!

A copy of ThirdPartyNotices.txt needs to be distributed with your product. The build scripts copy it automatically.

Supported Platforms

This plugin is available for the given platforms and architectures:

Except as noted, only building on the same platform as your target is supported. If you have troubles making a build or testing in the editor, try again with the Unity Editor running on your target platform.

This Asset does not include licenses for proprietary or patent-encumbered codecs such as h.264. (Most streaming sites use patent-encumbered codecs and will not work. YouTube videos generally work, unless they are live.) Consider re-encoding your content with an open codec supported by stock Chromium such as WebM or Ogg Vorbis.

OS X Users

Linux Users

Other Platforms

ZFBrowser is only supported on the platforms listed above right now. If you're interested in support for other platforms, please let me know! In most cases I can't simply port the existing backend to another OS, but having your votes will help me know what is most worthwhile to work on!


You can send and receive messages from the currently loaded browser page.

JavaScript vs UnityScript

Browsers run JavaScript, specifically, ECMAScript. JavaScript has a .js extension. Unity runs .NET languages, in particular: C# (.cs) and previously Boo (.boo) and UnityScript (.js). Due to a terrible historical mistake, UnityScript has been, and often still is, called "JavaScript". To be clear:

UnityScript IS NOT JavaScript.

In this package all references to "JavaScript" refer to what web browsers run. Beware that UnityScript and JavaScript files both have the same .js extension. In general, files in Assets/ with a .js extension will be treated as UnityScript and files in BrowserAssets/ with a .js extension will be treated as JavaScript.

Scripting Intro

Browsers have a Browser MonoBehaviour. You can call functions in the page by invoking CallFunction:

using ZenFulcrum.EmbeddedBrowser;
var browser = GetComponent<Browser>();//assuming we are a MonoBehaviour attached to the same GameObject as the Browser

//calls window.setPlayerStats("myPlayerName", 2, 4200, false) in the browser
browser.CallFunction("setPlayerStats", "myPlayerName", 2, 4200, false).Done();

Functions are resolved in the global scope of the top frame of the browser and executed with the given arguments. You can pass basic types (strings, integers, bools, etc.) without any extra effort.

You can also use EvalJS to run any JavaScript you'd like in the context of the page:

browser.EvalJS("if (someCondition()) someVar = 42;").Done();

To query the page for data, you can look at the return value. EvalJS and CallFunction don't execute immediately, they are asynchronous, therefore they return promises:

browser.EvalJS("document.title").Then(ret => Debug.Log("Document title: " + ret)).Done();
browser.CallFunction("doSomeFoo", 1, 2, 3).Then(ret => Debug.Log("Result: " + ret)).Done();

If you are in a Unity coroutine, you can wait for the promises to finish before continuing:

var promise = browser.EvalJS("document.title");
yield return promise.ToWaitFor();
Debug.Log("Document title: " + promise.Value);

This can be much easier to deal with in cases where you are chaining a lot of tasks.

You'll typically want to add .Done() after any EvalJS() or CallFunction() calls. This will add a default error handler that will log any unhandled exceptions or syntax errors in your code. You won't get errors for your evaluated code unless you call EvalJS(...).Done() or otherwise use the Promise API to handle the error. If you don't call .Done(), .Catch(), or the like your code will still execute, you just won't be notified if it fails.

See the promise section for more details on the promise library.

To receive events pushed from the page, you can expose a function callback. Do this with RegisterFunction:

browser.RegisterFunction("confirmClicked", args => Debug.Log("Button clicked: " + args[0] + " val: " + (int)args[1]));

Then you can call it from your page:

<!-- When this is clicked, Unity will log "Button clicked: button3 val: 13" -->
<button onclick="confirmClicked('button3', 13)">Confirm Things</button>



ZFBrowser uses this promise library made by Real Serious Games with some small changes.

Original documentation can be found here or online here.

This copy has been modified a bit from the version you can get from GitHub, namely:

The promise library is covered by the MIT license, as noted in ThirdPartyNoticies.txt.

Embedded Resources

You can embed web resources (HTML, JS, CSS, images, etc.) with your game and access them without the need for an external web server.

Place these resources in a folder named BrowserAssets next to your Assets folder, then access them with localGame://index.html instead of the usual http://example.com/index.html.



All mouse/keyboard input events are collected in Unity and forwarded to the underlying browser. How this input is sent can be customized.

VR Input

An input system is included for getting input from tracked VR controllers to point at and interact with a browser. Unity 2017.2 or newer is required.

Unity's VR controller input is a bit of a mess right now (see comment in VRInput.cs). To get input data form the controllers we use the direct APIs, which may require some extra setup.

First, do the usual setup to get VR running in your project (Player Settings » XR Settings). Then follow the instructions for the VR backend you are using below. Then look at the rest of this section.


Using the SteamVR runtime (and OpenVR API). This is for the HTC Vive, Oculus under SteamVR, and pretty much everything else.


Then you have a couple options:


Oculus VR


Once that's set up, you should be able to open up the VR demo scene and give it a try! (Use the VR (SteamVR 2.0) demo scene if you're using the SteamVR package with the new input system.)

To get things set up in your own scene:


External Keyboard

A world space keyboard is included for use with VR text entry and other times when a regular keyboard is not available. It can be linked to a browser and keystrokes entered on the virtual keyboard are passed to the browser.

Open the demo named ExternalKeyboard to try it out with your mouse!

This is mostly pure Qwerty layout without the top row. Modifiers have been swapped out for some shortcuts: select all text, undo/redo, and clipboard manipulation. There's some word-skipping buttons next to the arrows. You can also select characters/words by using shift followed by movement keys. There's also a few themes available. Click the ✩ where num lock would be to cycle through them.

You can customize the design of the keyboard, change the way a theme looks or which is the default, and even add or remove buttons. ZFBrowser/Resources/Browser/Keyboard.html contains the HTML for the keyboard. ExternalKeyboard.cs manages keyboard focus and typing/message routing.

To use it, drop the ExternalKeyboard prefab into your scene. By default it will link up to whichever browser seems to be focused, but you can toggle this behavior in the inspector. Also, take a look at the VR demo for an example.



Page Debugging

Often during development, you will find your pages need debugging.

Tip: You don't always have to restart the game to test a change, in some cases you can simply refresh the page. (Unity inspector » browser instance » Refresh or Page inspector » ctrl+r).

Here's a few way to go about it:

Page Inspector

You can access the Webkit/Chromium inspector, which opens in a new window beside the running game.

External Page Inspector

You can access the page inspector from another browser or IDE that supports Chromium's debugger.

Ordinary Browser

You can also load your pages in an ordinary browser and debug them there. If you do, you may find it useful to create small "log what happened" stubs for the functions you expose from Unity. Call functions you want to test from the JavaScript console.


By default cookies and profile data aren't saved between runs. Set BrowserNative.ProfilePath to a folder of your choice before the first Update to enable profile saving. (Or use a BrowserSystemSettings in your scene.)



The browser is rendered offscreen in a separate process and the resulting pixels are transferred to a texture. Performance will not be as good as native Chromium, but should generally be fair to decent.




Chromium doesn't play nice with others. To keep everyone happy and fix many bugs, Chromium is actually run in a separate process and we talk to it via IPC (a mixture of named pipes for messages and shared memory for the rendered buffer). You'll notice that your game spawns a ZFGameBrowser process which in turn spawns the usual Chromium child processes; this is normal.

Adobe Flash

This version of ZFBrowser includes some experimental support for Adobe Flash. Using this is discouraged and support for it may be removed in the future. Additional, note that Adobe plans to end support for Flash at the end of 2020.

Support for Flash is experimental. A command prompt window may flash while starting Flash content.

Enabling Flash requires some extra steps; see below.

Do I need it?

The Web is an evolving place and ever-increasingly interactive web sties don't need Flash to support media-rich content.

You need Flash if you want to:

Note that outdated versions of the Flash plugin may not function. User interaction may be required to start Flash content.

For myself (manual install)

If you are developing locally, prototyping, or will only distribute your application to computers that you control, use this method.


You'll need to install Flash on every computer you distribute your application to.

For anyone (distribute Flash)

To distribute Flash with your application, you'll need to get permission from Adobe and run their installer with your installer.

General flow: Untested, let me know how it goes!

Get Help

Need help? Go here!