WURFL InFuze Module for golang : User Guide

WURFL InFuze for golang is a GO language module wrapping the WURFL C API and encapsulating it in two golang types to provide a fast and intuitive interface. It is compatible on Linux and macOS platforms for golang 1.7 or higher.

Installing libwurfl

In order for the Module to work it is ESSENTIAL that the libwurfl library is installed on your system. libwurfl is provided in your Customer Vault/FileX.

If you have not already installed libwurfl, instructions can be found here. Release notes for each API can be found here.

Installation on Linux and macOS

InFuze for golang is available as a binary package. To install it, untar the contents in your GOPATH folder. For example:

# cd $GOPATH
# tar xvzf golang-src-wurfl-

WURFL Data Snapshot

To perform lookups, you will need a copy of your WURFL data snapshot (also referred to as the wurfl.xml). While there is one included in the release package, it is intended to be a sample and will not contain all of your licensed capabilities. Your licensed WURFL data snapshot can be accessed by following these directions.


Here is an example to get started:

package main

import (

func main() {

    var wengine *wurfl.Wurfl
    var device *wurfl.Device

    wengine, err := wurfl.Create("/usr/share/wurfl/wurfl.zip", nil, nil, -1, wurfl.WurflCacheProviderLru, "100000")

    if err != nil {

    ua := "Dalvik/1.6.0 (Linux; U; Android 4.3; SM-N900T Build/JSS15J)"

    device, err = wengine.LookupUserAgent(ua)

    deviceid, err := device.GetDeviceID()




Create the WURFL Engine once, then lookup UserAgent and get the static and virtual capabilities needed in your implementation (NOTE: virtual capabilities are calculated at runtime).

If you already have a HTTP request, you can directly pass it to the WURFL API by using wengine.LookupRequest(). Alternately you can test passing a HTTP request to the WURFL API by creating a mock request, stuffing it with the desired test headers and passing them to the WURFL API as mentioned in the previous sentence. This is particularly useful for detecting requests with User-Agent Client Hints. In either case you can retrieve the resolved device as shown below. The static and virtual capabilities can then be requested as shown in the first snippet.

    req, _ := http.NewRequest("GET", "http://example.com", nil)
    UserAgent := "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/ Mobile Safari/537.36"
    req.Header.Add("User-Agent", UserAgent)
    req.Header.Add("Sec-CH-UA", "\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"110\", \"Google Chrome\";v=\"110\"")
    req.Header.Add("Sec-CH-UA-Full-Version", "110.0.4430.91")
    req.Header.Add("Sec-CH-UA-Platform", "Android")
    req.Header.Add("Sec-CH-UA-Platform-Version", "11")
    req.Header.Add("Sec-CH-UA-Model", "SM-M315F")

    device, err = wengine.LookupRequest(req)

Additional documentation on User-Agent Client Hints and how to collect them is available here.

WURFL Updater

If you want to keep your wurfl.zip uptodate with the ScientiaMobile data release schedule, then you might want to use the Updater features.

After creating your WURFL Engine, set your personal WURFL Snapshot URL (in the form https://data.scientiamobile.com/xxxxx/wurfl.zip, with xxxxx replaced with your personal access token, located in your customer vault):

uerr := wengine.SetUpdaterDataURL(Url)
if uerr != nil {
    fmt.Printf("SetUpdaterDataUrl returned : %s\n", uerr.Error())

Specify the periodicity you would like for update checks:

_ = wengine.SetUpdaterDataFrequency(wurfl.WurflUpdaterFrequencyDaily)

Do note that a wurfl.zip file must already be present in a writable path in order for the updater to check the file and determine whether or not it needs to update the file. You can either manually download this file by going to your WURFL Snapshot URL or by following these directions.

Start the updater:

uerr = wengine.UpdaterStart()
if uerr != nil {
  fmt.Printf("UpdaterStart returned : %s\n", uerr.Error())

Updater will run a daily check for the latest release of the wurfl.zip file, download it, and update the running engine to the latest version - all during normal application operations.

Checking User-Agent frozenness and HTTP headers quality

Starting from version the Wurfl struct provides two new methods: IsUserAgentFrozen(), GetHeaderQuality().

IsUserAgentFrozen(ua string) returns a boolean value which, if true, means that the input User-Agent string won't be updated by the sender browser.

GetHeaderQuality() returns an enumeration value that describes the HTTP headers quality. It has three possible values:

  • HeaderQualityFull: all the headers needed for a successful WURFL detection are present. Eg. a header with all UA-CH header fields present
  • HeaderQualityBasic: only some of the headers needed for a successful WURFL detection are present.
  • HeaderQualityNone: no UA-CH headers are present

API Reference


Package files

  • interface.go (/src/scientiamobile/wurfl/interface.go)
  • wurfl.go (/src/scientiamobile/wurfl/interface.go)


EngineTarget (DEPRECATED as of

const (
    WurflEngineTargetHighAccuray             = C.WURFL_ENGINE_TARGET_HIGH_ACCURACY
    WurflEngineTargetHighPerformance         = C.WURFL_ENGINE_TARGET_HIGH_PERFORMANCE
    WurflEngineTargetDefault                 = C.WURFL_ENGINE_TARGET_DEFAULT

UserAgentPriority (DEPRECATED as of

const (
    WurflUserAgentPriorityUsePlainUserAgent                  = C.WURFL_USERAGENT_PRIORITY_USE_PLAIN_USERAGENT

WurflCacheProvider (DEPRECATED as of

const (
    WurflCacheProviderDefault = -1
    WurflCacheProviderNone    = C.WURFL_CACHE_PROVIDER_NONE
    WurflCacheProviderLru     = C.WURFL_CACHE_PROVIDER_LRU
    // Deprecated: use WurflCacheProviderLru instead
    WurflCacheProviderDoubleLru = C.WURFL_CACHE_PROVIDER_DOUBLE_LRU


const (
    WurflMatchTypeExact           = C.WURFL_MATCH_TYPE_EXACT
    WurflMatchTypeConclusive      = C.WURFL_MATCH_TYPE_CONCLUSIVE
    WurflMatchTypeRecovery        = C.WURFL_MATCH_TYPE_RECOVERY
    WurflMatchTypeCatchall        = C.WURFL_MATCH_TYPE_CATCHALL
    WurflMatchTypeHighPerformance = C.WURFL_MATCH_TYPE_HIGHPERFORMANCE
    WurflMatchTypeNone            = C.WURFL_MATCH_TYPE_NONE
    WurflMatchTypeCached          = C.WURFL_MATCH_TYPE_CACHED


const (
    WurflEnumStaticCapabilities    = C.WURFL_ENUM_STATIC_CAPABILITIES
    WurflEnumVirtualCapabilities   = C.WURFL_ENUM_VIRTUAL_CAPABILITIES
    WurflEnumMandatoryCapabilities = C.WURFL_ENUM_MANDATORY_CAPABILITIES
    WurflEnumWurflID               = C.WURFL_ENUM_WURFLID


const (
    WurflUpdaterFrequencyDaily  = C.WURFL_UPDATER_FREQ_DAILY
    WurflUpdaterFrequencyWeekly = C.WURFL_UPDATER_FREQ_WEEKLY

WURFL Extra Headers (DEPRECATED as of

const (
    WurflAttrExtraHeadersExperimental = C.WURFL_ATTR_EXTRA_HEADERS_EXPERIMENTAL

func APIVersion

Returns version of internal InFuze API without needing an initialized engine

func APIVersion() string

type Device

Represents the internal matched device handle

type Device struct {
    Device C.wurfl_device_handle
    Wurfl  C.wurfl_handle

func (*Device) Destroy

Destroys the device handle. This should be called when when device attributes are not needed anymore.

func (d *Device) Destroy()

func (*Device) GetCapabilities

Get the capability values for a list of static capabilities

func (d *Device) GetCapabilities(caps []string) map[string]string

func (*Device) GetCapability

Get the capability values for a single static capability

func (d *Device) GetCapability(cap string) string

func (*Device) GetDeviceID

Gets the device ID (WURFL ID) from the device handle

func (d *Device) GetDeviceID() (string, error)

func (*Device) GetMatchType

Returns the matchtype from the device lookup

func (d *Device) GetMatchType() int

func (*Device) GetNormalizedUserAgent

Gets the normalized (processed by the WURFL API) User-Agent

func (d *Device) GetNormalizedUserAgent() (string, error)

func (*Device) GetOriginalUserAgent

Gets the original User-Agent (the one that was passed for the lookup)

func (d *Device) GetOriginalUserAgent() (string, error)

func (*Device) GetRootID

Gets the root WURFL ID for the current device

func (d *Device) GetRootID() string

func (*Device) GetUserAgent

Gets default User-Agent of matched device from the WURFL snapshot (might be different from the one passed for the lookup)

func (d *Device) GetUserAgent() (string, error)

func (*Device) GetVirtualCapabilities

Get the capability values for a list of virtual capabilities

func (d *Device) GetVirtualCapabilities(caps []string) map[string]string

func (*Device) GetVirtualCapability

Get the capability values for a single virtual capability

func (d *Device) GetVirtualCapability(vcap string) string

func (*Device) IsRoot

Returns true if the looked up device is a device root

func (d *Device) IsRoot() bool

type DeviceHandler

Defines API methods for the Wurfl Device handle

type DeviceHandler interface {
    GetMatchType() int
    GetVirtualCapabilities(caps []string) map[string]string
    GetVirtualCapability(vcap string) string
    GetCapabilities(caps []string) map[string]string
    GetCapability(cap string) string
    IsRoot() bool
    GetRootID() string
    GetDeviceID() (string, error)
    GetNormalizedUserAgent() (string, error)
    GetOriginalUserAgent() (string, error)
    GetUserAgent() (string, error)

type HeaderQuality

Gets the header quality value

type HeaderQuality int

func (HeaderQuality) String

Converts a header quality to a string

func (hq HeaderQuality) String() string

The various header quality values are listed below:

const (
    // HeaderQualityNone no User Agent Client Hints are present.
    HeaderQualityNone HeaderQuality = C.WURFL_ENUM_UACH_NONE
    // HeaderQualityBasic only some of the headers needed for a successful WURFL detection are present.
    HeaderQualityBasic HeaderQuality = C.WURFL_ENUM_UACH_BASIC
    // HeaderQualityFull all the headers needed for a successful WURFL detection are present.
    HeaderQualityFull HeaderQuality = C.WURFL_ENUM_UACH_FULL

type Updater

Defines the API methods for the Updater

type Updater interface {
    SetUpdaterDataURL(DataURL string) error
    SetUpdaterDataFrequency(Frequency int) error
    SetUpdaterDataURLTimeout(ConnectionTimeout int, DataTransferTimeout int) error
    SetUpdaterLogPath(LogFile string) error
    UpdaterRunonce() error
    UpdaterStart() error
    UpdaterStop() error

type Wurfl

Represents internal WURFL Infuze handle

type Wurfl struct {
    Wurfl                C.wurfl_handle
    ImportantHeaderNames []string
    // contains filtered or unexported fields

func Create

Creates the WURFL engine parameters:

  • Wurflxml: path to the wurfl.xml/zip file
  • Patches: slice of paths of patches files to load
  • CapFilter: list of capabilities used; allow to init engine without loading all 500+ caps
  • EngineTarget: the desired engine target (DEPRECATED as of
  • CacheProvider: WurflCacheProviderLru or WurflCacheProviderDoubleLru
  • CacheExtraConfig: size of single or double lru caches in the form "100000" or "100000,30000"
func Create(Wurflxml string, Patches []string, CapFilter []string, EngineTarget int, CacheProvider int, CacheExtraConfig string) (*Wurfl, error)

func (*Wurfl) Destroy

Destroys the WURFL engine

func (w *Wurfl) Destroy()

func (*Wurfl) GetAPIVersion

Gets the version of underlying WURFL InFuze API

func (w *Wurfl) GetAPIVersion() string

func (*Wurfl) GetAllCaps

Returns all the names of the static capabilities present in the loaded WURFL snapshot

func (w *Wurfl) GetAllCaps() []string

func (*Wurfl) GetAllDeviceIds

Returns a slice containing all device IDs (WURFL IDs) present in the loaded WURFL snapshot

func (w *Wurfl) GetAllDeviceIds() []string

func (*Wurfl) GetAllVCaps

Returns all the names of the virtual capabilities present in the loaded WURFL snapshot

func (w *Wurfl) GetAllVCaps() []string

func (*Wurfl) GetAttr

Gets the WURFL engine attributes

func (w *Wurfl) GetAttr(attr int) (int, error)

func (*Wurfl) GetEngineTarget

(DEPRECATED as of Returns a string representing the currently set WURFL Engine Target. Possible values are:

func (w *Wurfl) GetEngineTarget() string

func (*Wurfl) GetHeaderQuality

Gets the header quality of the request

func (w *Wurfl) GetHeaderQuality(r *http.Request) (HeaderQuality, error)

func (*Wurfl) GetInfo

Gets the information about the wurfl.xml file (WURFL snapshot)

func (w *Wurfl) GetInfo() string

func (*Wurfl) GetLastLoadTime

Gets the time the wurfl.xml was last loaded

func (w *Wurfl) GetLastLoadTime() string

func (*Wurfl) GetUserAgentPriority

DEPRECATED Tells if WURFL is using the plain User-Agent or the sideloaded browser User-Agent for device detection

func (w *Wurfl) GetUserAgentPriority() string

func (*Wurfl) HasCapability

Returns true if the static capability exists

func (w *Wurfl) HasCapability(cap string) bool

func (*Wurfl) HasVirtualCapability

Returns true if the virtual capability exists

func (w *Wurfl) HasVirtualCapability(vcap string) bool

func (*Wurfl) IsUserAgentFrozen

Returns true if the User-Agent is frozen

func (w *Wurfl) IsUserAgentFrozen(ua string) bool

func (*Wurfl) LookupDeviceID

Performs a lookup by device ID (WURFL ID) and returns a device handle

func (w *Wurfl) LookupDeviceID(DeviceID string) (*Device, error)

func (*Wurfl) LookupDeviceIDWithImportantHeaderMap

Performs a lookup using the device ID (WURFL ID) and the header values found in a ImportantHeaderMap (IHMap), and returns a device handle. The IHMap must be filled with values from Wurfl.ImportantHeaderNames.

func (w *Wurfl) LookupDeviceIDWithImportantHeaderMap(DeviceID string, IHMap map[string]string) (*Device, error)

func (*Wurfl) LookupDeviceIDWithRequest

Performs a lookup using the device ID (WURFL ID) and request headers, and returns a device handle

func (w *Wurfl) LookupDeviceIDWithRequest(DeviceID string, r *http.Request) (*Device, error)

func (*Wurfl) LookupRequest

Performs a lookup using request headers and returns a device handle

func (w *Wurfl) LookupRequest(r *http.Request) (*Device, error)

func (*Wurfl) LookupUserAgent

Performs a lookup using User-Agent and returns a device handle

func (w *Wurfl) LookupUserAgent(ua string) (*Device, error)

func (*Wurfl) LookupWithImportantHeaderMap

Performs a lookup using the header values found in a ImportantHeaderMap (IHMap) and returns a device handle. The IHMap must be filled with values from Wurfl.ImportantHeaderNames.

func (w *Wurfl) LookupWithImportantHeaderMap(IHMap map[string]string) (*Device, error)

func (*Wurfl) SetAttr

Sets WURFL engine attributes

func (w *Wurfl) SetAttr(attr int, value int) error

func (*Wurfl) SetUpdaterDataFrequency

Sets the interval of WURFL updater checks

func (w *Wurfl) SetUpdaterDataFrequency(Frequency int) error

func (*Wurfl) SetUpdaterDataURL

Sets the interval of WURFL updater checks. Typically your https updater URL from your ScientiaMobile vault.

func (w *Wurfl) SetUpdaterDataURL(DataURL string) error

func (*Wurfl) SetUpdaterDataURLTimeout

Sets the connection and data transfer timeouts (in millisecs) for the WURFL updater HTTP call. 0 for no timeout, -1 for the default value.

func (w *Wurfl) SetUpdaterDataURLTimeout(ConnectionTimeout int, DataTransferTimeout int) error

func (*Wurfl) SetUpdaterLogPath

Sets the path of WURFL updater log file

func (w *Wurfl) SetUpdaterLogPath(LogFile string) error

func (*Wurfl) SetUserAgentPriority

(DEPRECATED as of Tells WURFL to use either the plain User-Agent or the sideloaded browser User-Agent for device detection

func (w *Wurfl) SetUserAgentPriority(prio int)

func (*Wurfl) UpdaterRunonce

Runs the WURFL updater process once and waits for termination

func (w *Wurfl) UpdaterRunonce() error

func (*Wurfl) UpdaterStart

Starts the updater thread

func (w *Wurfl) UpdaterStart() error

func (*Wurfl) UpdaterStop

Stop the updater thread

func (w *Wurfl) UpdaterStop() error

© 2024 ScientiaMobile Inc.
All Rights Reserved.

NOTICE: All information contained herein is, and remains the property of ScientiaMobile Incorporated and its suppliers, if any. The intellectual and technical concepts contained herein are proprietary to ScientiaMobile Incorporated and its suppliers and may be covered by U.S. and Foreign Patents, patents in process, and are protected by trade secret or copyright law. Dissemination of this information or reproduction of this material is strictly forbidden unless prior written permission is obtained from ScientiaMobile Incorporated.