Build scans are an important tool for developing and maintaining Gradle builds. They provide insights into exactly what your builds are doing, helping you identify problems with the build environment, dependencies, performance, and more. They can also help you understand and improve the build more generally, and make collaborating with others easier.

build scan service overview
Figure 1. Build scans can be published to Gradle Enterprise or

Gradle Enterprise is a commercial product for companies that can be hosted on their own systems and ships with a build scan server and a build cache backend implementation. is a build scan server available for free, hosted by Gradle Inc.

Getting set up

There are two aspects to working with build scans:

  • Data collection

  • Publishing

You can have data collection without publishing the information, but you usually want to do both.

Here are two examples —one for Gradle Enterprise and one for— that demonstrate how to collect build data and publish it as a build scan every time you run the build:

Gradle Enterprise
plugins {
    id '' version '1.16'                    (1)

buildScan {
    server = ''           (2)

    publishAlways()                                              (3)
1 Applies the build scan plugin
2 Configures the Gradle Enterprise server to publish to
3 Publishes a build scan every time a build runs
plugins {
    id '' version '1.16'                     (1)

buildScan {
    termsOfServiceUrl = ''     (2)
    termsOfServiceAgree = 'yes'                                   (2)

    publishAlways()                                               (3)
1 Applies the build scan plugin
2 Configures acceptance of the terms of service
3 Publishes a build scan every time a build runs

Next, you will learn all the relevant options available to configure the data collection and publication of build scans.

Applying the plugin

You can apply the build scan plugin to individual builds, or to all builds on a machine via an init script. Let’s take a look at the configuration you need for each of these scenarios.

For individual builds

You apply the build scan plugin to a build file in the same way that you apply any other plugin. The build scan plugin must be applied to the root project only, not to subprojects.

Gradle 2.1+
plugins {
  id '' version '1.16'
Gradle 2.0+
buildscript {
  repositories {
      maven { url '' }
  dependencies {
      classpath 'com.gradle:build-scan-plugin:1.16'
apply plugin: ''

Check the compatibility guide for more information about build scan plugin version compatibility.

When using Gradle <4.3 or build scan plugin <1.10, make sure you declare the build scan plugin before any other plugin. This ensures that any relevant configuration data from those plugins is included in the build scans.

Do Don’t
plugins {
  id '' version '1.16'
  id 'java'
plugins {
  id 'java'
  id '' version '1.16'

The order used by the second example won’t break the build scans that you publish, but they will be missing useful information.

For all your builds

You may find build scans so useful that you want to enable them always, regardless of which build you are running. If that’s the case, you can create a Gradle init script that automatically applies the build scan plugin to every build. Here’s an example init script that you can use to do just that:

initscript {
    repositories {
        maven { url '' }
    dependencies {
        classpath 'com.gradle:build-scan-plugin:1.16'
rootProject {
    apply plugin: com.gradle.scan.plugin.BuildScanPlugin

The ~ in the file path for the init script represents the absolute path to your user home directory. This is the same as the %UserProfile% environment variable on Windows.

Applying the plugin enables the data collection, but you won’t be able to publish build scans until you’ve added some extra configuration. What that configuration looks like depends on where you want to publish those build scans.

Enabling publication of build scans

The last bit of configuration you need depends on whether you are publishing to a Gradle Enterprise instance or In the case of Gradle Enterprise, you need to specify the server’s location. In the case of, you need to accept the terms of service.

Set the location of your Gradle Enterprise instance

When you publish build scans to a Gradle Enterprise instance, you must configure the location of the Gradle Enterprise server.

Add the following configuration to the build script—or the rootProject {} block of the init script if you are using that approach—ensuring that it appears after the build scan plugin is declared or applied:

Specifying the location of your Gradle Enterprise server
buildScan {
  server = ''

The precise URL you need depends on the hostname your Gradle Enterprise instance has been configured with. If in doubt, be sure to ask whomever manages that instance.

You may encounter a warning about an untrusted certificate every time you try to publish a build scan to an HTTPS URL. The ideal solution is for someone to add a valid SSL certificate to the Gradle Enterprise instance, but we recognise that you may not be able to do that. In which case, set the allowUntrustedServer option to true:

Disabling SSL certificate checks
buildScan {
    server = '...'
    allowUntrustedServer = true

This is a convenient workaround, but you shouldn’t use it as a long-term solution.

Accept the terms of service

In order to publish to, you need to accept the terms of service, by adding the following configuration to the build script —or the rootProject {} block of the init script if you’re using that approach— ensuring that it appears after the plugin is declared or applied:

build scan plugin 1.12+
buildScan {
    termsOfServiceUrl = ''
    termsOfServiceAgree = 'yes'
build scan plugin < 1.12
buildScan {
    licenseAgreementUrl = ''
    licenseAgree = 'yes'

Be sure to check the terms of service at the URL shown in the above code fragment.

Once you have accepted the terms of service, you can start publishing build scans to

If you don’t accept the terms of service in your build script, as explained above, and you use Gradle 4.3+ and build scan plugin 1.9.1+, you will be asked to agree to the terms of service on the command line, before any attempt of publishing a build scan. This can be useful if you share your build script with others, and you want everyone to explicitly accept those terms of service.

Controlling when build scans are published

Once you’ve gone through the initial setup of the previous section, you are ready to start publishing build scans. But when should you publish them? Every time you run a build? Only when the build fails? It’s up to you. The build scan plugin has several options that allow you to use whatever approach works best.

Publishing on demand

We imagine that when you first start experimenting with build scans, you won’t want to publish them all the time until you become familiar with the implications. Even then, you may have good reason not to go all-in and automate the process. That’s where one-off build scans come in.

As long as build scans are enabled for a build, you can always publish one by passing the --scan option to Gradle. For example, each of the following will result in a published build scan:

$ gradle assemble --scan
$ gradle clean build --scan

When using Gradle 4.3+ and the build scan plugin has not been applied, the plugin will be applied automatically by Gradle when running your build with the --scan command-line parameter. The build scan plugin version being applied in this case depends on your Gradle version, but it will always be the latest version available at the time the Gradle version was released.

When using Gradle <3.4 or a build scan plugin version <1.6, you have to publish build scans using the -Dscan system property instead of --scan.

Behind the scenes, Gradle captures information about the build while it runs and then publishes the data to the configured Gradle Build Scan Service at the end.

There may be occasions when you want to publish a build scan for the previous run. Perhaps you noticed something interesting about the build from its output and would like to review a build scan for it. The build scan plugin supports this situation by providing a buildScanPublishPrevious task that publishes the data that was collected from the previous run:

$ gradle buildScanPublishPrevious

Since the task name is quite long, it’s worth taking advantage of Gradle’s abbreviated command line notation for tasks:

$ gradle bSPP

Be aware that the task only works for the previous build execution, so if you remember too late and want to publish the build scan for three builds ago, you’ll need to run the build again. At that point, you should consider automating the publication of build scans.

Publishing every build run

There are advantages to publishing build scans regularly, such as being able to track the behavior and performance of a build over time. It makes no sense relying on the --scan option in such a situation as it’s easy to forget this little tweak to the command line.

When you want to publish every build run, you can use the publishAlways setting:

Publishing a build scan for every build execution
buildScan {

This approach means that you get a build scan for every successful and failed build that runs, including from your continuous integration infrastructure and your developers. That may work for you, but if you find it overwhelming or simply not useful, add some publication criteria as demonstrated in the following section.

Publishing based on criteria

Many of you will want a bit more control over exactly when build scans are published without resorting to using --scan each time. Perhaps you only want to publish build scans when the build fails, or if the build is running on your continuous integration infrastructure. Such scenarios are covered by the options in the following table.

Table 1. Options for automatic publishing based on criteria
Option Description


Publish a build scan if the given condition is true, regardless of whether the build succeeds or fails.


Publish a build scan only when the build fails.


Publish a build scan only if the condition is true and the build fails.

For example, let’s say you only want to publish build scans from your CI system, which is identified by having a CI environment variable. This configuration will do the trick:

Restricting build scans to a CI system
buildScan {

You can use the other options in the same way. If you want to configure several things based on a set of criteria, you can use an if condition instead:

buildScan {
    if (System.getenv('CI')) {
        tag 'CI'

Extending build scans

(build scan plugin v1.1+)

You can easily include extra custom information in your build scans in the form of tags, links and values. This is a very powerful mechanism for capturing and sharing information that is important to your build and development process.

This information can be anything you like. You can tag all builds run by your continuous integration tool with a CI tag. You can capture the name of the environment that the build published to as a value. You can link to the source revision for the build in an online tool such as GitHub. The possibilities are endless.

You can see how the custom data appears in figure 2:

scan with custom data
Figure 2. A build scan containing the different types of custom data

Gradle Enterprise allows listing and searching across all of the build scans in the system. You can find and filter build scans by tags and custom values, in addition to project name, outcome and other properties. In figure 3, for example, we are filtering for all build scans that have the tag "CI" and a git branch name of "master":

build scan filtered list
Figure 3. A filtered list of build scans in Gradle Enterprise

Adding tags

Tags are typically used to indicate the type or class of a build, or a key characteristic. They are prominent in the user interface and quickly inform a user about the nature of a build. A build can have zero or more tags.

They can be added at build time via the tag() method:

Adding tags to a build’s build scans
buildScan {
    if (System.getenv('CI')) {
        tag 'CI'
    } else {
        tag 'Local'

    tag System.getProperty('')

As demonstrated by the example above, tags are typically applied either as fixed strings within a condition or evaluated at runtime from the environment. But there are no set rules that you need to follow—these are only suggestions.

The syntax for adding a tag is:

tag <tag>

where the <tag> is a string.

Note that the order in which you declare the tags doesn’t affect the build scan view. They are displayed in alphabetical order, with any all-caps labels displayed before the rest.

Build scan plugin v1.9.1+ impose limits on captured tags:

  • maximum tag count: 50

  • maximum tag length: 200 characters

Builds rarely live in isolation. Where does the project source live? Is there online documentation for the project? Where can you find the project’s issue tracker? If these exist and have a URL, you can add them to the build scan.

They can be added at build time via the link() method:

Adding a VCS URL to a build’s build scans
buildScan {
    link 'VCS', '${System.getProperty('vcs.branch')}'

The above example demonstrates how you can attach a link to an online VCS repository that points to a specific branch provided as a system property.

The syntax for adding a link is:

link <label>, <URL>

The <label> is simply a string identifier that you choose and that means something to you.

You can see the effect of a custom link in figure 2, which shows how a label Source becomes a hyperlink that anyone viewing the build scan can follow.

Build scan plugin v1.9.1+ impose limits on captured links:

  • maximum link count: 20

  • maximum link label length: 100 characters

  • maximum link url length: 1,000 characters

Adding custom values

Some information just isn’t useful without context. What does "1G" mean? You might guess that it represents 1 gigabyte, but of what? It’s only when you attach the label "Max heap size for build" that it makes sense. The same applies to git commit IDs, for example, which could be interpreted as some other checksum without a suitable label.

Custom values are designed for these cases that require context. They’re standard key-value pairs, in which the key is a string label of your choosing and the values are also strings, often evaluated from the build environment.

They can be added at build time via the value() method:

Adding custom values to a build’s build scans
buildScan {
    value 'Build Number', project.buildNumber

The above example demonstrates how you can read the build number from a project property—assuming you have your build set up for this—and attach it to the build scans as a custom value.

The syntax for adding a value is:

value <key>, <value>

where both the <key> and the <value> are strings.

As with tags, you can filter build scans by custom values in Gradle Enterprise.

Build scan plugin v1.9.1+ impose limits on captured custom values:

  • maximum custom value count: 1,000

  • maximum custom value key length: 1,000 characters

  • maximum custom value value length: 100,000 characters

Adding data at the end of the build

(build scan plugin v1.2+)

The examples you have seen so far work well if when the custom data is available at the beginning of the build. But what if you want to attach data that’s only available later? For example, you might want to label a build as "built-from-clean" if the clean task was run. But you don’t know if that’s the case until the task execution graph is ready.

The build scan plugin provides a buildFinished() hook that you can use for these situations. It defers attaching custom data until the build has finished running. As an example, imagine you want to report how much disk space was taken up by the output build directory. The build doesn’t know this until it’s finished, so the solution is to calculate the disk space and attach it to a custom value in the buildFinished() hook:

Adding a custom disk usage value at the end of the build
buildScan {
    buildFinished {
        value 'Disk usage (output dir)', buildDir.directorySize()

The buildFinished() closure has access to the rest of the build, including the Project instance, so it can extract all sorts of information. It also has access to a BuildResult instance that you can use to determine whether the build failed or not, like so:

Checking build status from buildFinished()
import com.gradle.scan.plugin.BuildResult
buildScan {
    buildFinished { BuildResult result ->
        if (result.failure) {
            value 'Failed with', result.failure.message

The Gradle build tool has a BuildListener interface that also contains a buildFinished() hook. However, you cannot use this to attach custom data because it is triggered too late. You can use hooks like project.afterEvaluate() or the buildStarted() method of BuildListener because they are executed early enough.

Adding expensive data

(build scan plugin v1.15+)

Some data that you may wish to add to your build scan can be expensive to capture. For example, capturing the Git commit ID may require executing the git command as an external process, which is expensive. To do this without slowing your build down, you can use the buildScan.background() method:

Using background() to capture an expensive custom value
buildScan {
    background {
       def commitId = 'git rev-parse --verify HEAD'.execute().text.trim()
       value "Git Commit ID", commitId

This method takes a function that will be executed on a separate thread, which allows Gradle to continue without waiting for the expensive work to complete.

All background work will be completed before finishing the build and publishing the build scan.

Any errors that are thrown by the background action will be logged and captured in the build scan.

See the buildScan.background() API reference for more information.

Providing custom data via system properties

(build scan plugin v1.3+)

The examples up to this point have shown how your build file or init script can pull information from the environment, via environment variables and system properties. The build scan plugin also allows you to inject any form of custom data through the use of specially named system properties. This can help you keep your build files clean of too much environment-specific information that may not be relevant to most of the users of the build.

These system properties take the following forms, depending on whether you want to inject a link, a tag or a custom value:


Here are some concrete examples, which assume that the build has been configured to publish build scans automatically:

$ gradle build -Dscan.tag.CI
$ gradle build
$ gradle build "-Dscan.value.CI Build Type=QA_Build"

This feature is particularly useful for continuous integration builds as you can typically easily configure your CI tool to specify system properties for a build. It’s even common for CI tools to be able to inject system properties into a build that are interpolated with information from the CI system, such as build number.

$ gradle build "-Dscan.value.buildNumber=$CI_BUILD_NUMBER"

Capturing the build scan ID or address

(build scan plugin v1.9+)

The address of the build scan is included in the output at the end of the build. However, you may wish to record the ID or URL of the build scan in some other way. The build scan plugin allows you to register a callback that will receive this information. The callback is invoked after a build scan has been successfully published.

The example build script snippet below shows this feature being used to maintain a journal of created build scans.

Gradle Enterprise provides the ability to search for build scans created by a certain user and/or from a particular host (along with other search criteria).

Creating a log of published build scans
import com.gradle.scan.plugin.PublishedBuildScan
buildScan {
    buildScanPublished { PublishedBuildScan scan ->
        file('scan-journal.log') << "${new Date()} - ${scan.buildScanId} - ${scan.buildScanUri}\n"

Please see the buildScan.buildScanPublished() method for API details.


Slow build startup in MacOS Sierra after applying build scan plugin

An issue with resolving localhost affecting MacOS Sierra can cause a 5 second delay after applying the build scan plugin to your build. Until the issue is fixed, there is a workaround that you can apply to your /etc/hosts file. Add these lines to your /etc/hosts file, substituting your computer name for 'mbpro' in the below snippet:

/etc/hosts   localhost mbpro.local
::1         localhost mbpro.local

Appendix A: API reference

Please see the Javadoc.

Appendix B: Captured information

The build scan plugin captures information while the build is running and transmits it to a server after the build has completed.

Most of the information captured can be considered to be build data. This includes the name of the projects in your build, the tasks, plugins, dependencies, names and results of tests and other things of this nature. Some more general environmental information is also captured. This includes your Java version, operating system, hardware, country, timezone and other things of this nature.

Notably, the actual source code being built and the output artifacts are not captured. However, error messages emitted by compilers or errors in tests may reveal aspects of the source code.


The list below details the notable information captured by the build scan plugin and transmitted in a build scan.

  • Environment

    • Build Java Virtual Machine

    • Username (system property '')

    • Local hostname (environment variable 'COMPUTERNAME' / 'HOSTNAME')

    • Public hostname

    • IP addresses

    • Operating System

    • Hardware

  • Build

    • Gradle command-line and invocation options (e.g. requested tasks, switches)

    • Executed task names and outcomes (e.g. FAILED, UP-TO-DATE)

    • Build console output

    • Build failure exception messages and stacktraces

    • Project names and structure

    • Executed tests (using Gradle’s JVM Test task)

    • Applied plugins

    • Resolved dependencies

    • Gradle Daemon operational data (e.g. start time, build count)

    • Network downloads (performed by Gradle)


Build scans published to a Gradle Enterprise installation are viewable by all users that can reach the server. Gradle Enterprise provides a search interface for discovering and finding individual build scans.

Build scans published to are viewable by anyone with the link assigned when publishing the build scan. Links to individual build scans are not discoverable and cannot be guessed, but may be shared.

Appendix C: Plugin release history

1.16 - 21st August 2018
Capture repositories and source repository for a resolved module component
Capture individual lifecycle listeners and attribute to code unit application
Capture Gradle build script compilation details
Capture deprecated usage notifications
Capture source of included build

1.15.2 - 10th August 2018
Fix for Kotlin script build caching

1.15.1 - 5th July 2018
Fix for potential classloader leak when using buildScan.background()

1.15 - 3rd July 2018
Support capturing expensive custom values/tags/links in the background
Task buildScanPublishPrevious is created lazily
Fixed error when using included build as plugin and in main build

1.14 - 12th June 2018
Further performance improvements
Removal of unnecessary implicit continuous build scan suppression
Capture information on lifecycle hook execution

1.13.4 - 18th May 2018
Improved performance of build scan plugin, particularly during configuration time

1.13.3 - 14th May 2018
Fix incompatibility with new continuous build features in Gradle 4.7

1.13.2 - 8th May 2018
Do not show build scan publishing information when --quiet or -q argument is present
Retry likely temporary network errors while publishing a build scan

1.13.1 - 10th Apr 2018
Improve performance of plugin data capture.

1.13 - 28th Mar 2018
Capture console log from beginning of the build.

1.12.1 - 13th Feb 2018
Fix message when terms of service are declined.

1.12 - 12th Feb 2018
Capture build scans for composite builds.
Capture original task execution time.

1.11 - 5th Dec 2017
Capture test execution, dependency resolution, and project structure data from the beginning of the build.
Improve performance of plugin data capture.
Enhance Gradle version compatibility check.

1.10.3 - 23th Nov 2017
Fix incompatibility with Android Plugin for Gradle 3.0.0.

1.10.2 - 7th Nov 2017
Fix incompatibility with development builds of Gradle 4.4.

1.10.1 - 27th Oct 2017
Fix incompatibility with development builds of Gradle 4.4.

1.10 - 17th Oct 2017
Detect when build was run by a single-use daemon.
Capture default charset of the JVM that executed the build.
Capture build path of each project.

1.9.1 - 10th Oct 2017
Prompt user for license agreement acceptance, if needed.
Capture console output and network activity until closer to the end of the build.
Limit the number and length of captured custom tags, custom links, and custom values.

1.9 - 15th Aug 2017
Capture task graph calculation.
Capture more fine-grained project configuration.
Capture build cache interactions including artifact packing and unpacking.

1.8 - 15th June 2017
Capture resolved requested tasks.
Capture build cache configuration when build cache is enabled.
Capture task inputs for each task when build cache is enabled.
Capture origin build invocation id for tasks with up-to-date and from-cache outcome.
Capture reasons why a task was not up-to-date.
Capture GC and peak heap memory statistics.
Capture more network download activities.
Get notified after successful build scan publication via buildScan.buildScanPublished().
Build scan plugin logs at quiet level.

1.7.4 - 29th May 2017
Fix incompatibility with development builds of Gradle 4.0.

1.7.3 - 19th May 2017
Fix incompatibility with development builds of Gradle 4.0.

1.7.2 - 17th May 2017
Fix incompatibility with development builds of Gradle 4.0.

1.7.1 - 3rd May 2017
Fix incompatibility with development builds of Gradle 4.0.

1.7 - 24th April 2017
Fix NPE when specifying buildScan 'server' URL without schema or host.
Overlapping output is captured as a non-cacheable reason for a task.

1.6 - 10th February 2017
Capture whether task outputs are cacheable and the reason if they are not.
Capture network download activities.

1.5 - 11st January 2017
Capture whether tasks were skipped due to having no source.
Capture whether tasks are lifecycle tasks (i.e. no actions).
Add 'mailto:' link as custom build scan links.

1.4 - 21st December 2016
Performance improvements when executing many tests.

1.3 - 15th November 2016
Capture tags, links and/or values via conventional system properties.
Reduced payload size when publishing large dependency graphs.

1.2 - 12th October 2016
Capture tags, links and/or values at the end of the build via buildScan.buildFinished().

1.1.1 - 20th September 2016
Fixed issues with creating build scans for some projects via Android Studio.

1.1 - 17th September 2016
Capture user-defined tags, links and arbitrary values.
Create a build scan for every build, or every failed build.
Create a build scan for the immediately previous build.
Publishing a build scan is implicitly disabled when build with --offline.
Publish a build scan over an untrusted HTTPS connection, if explicitly configured.
Several fixes for creating build scans when executing a build through an IDE.

1.0 - 23rd June 2016
Initial release.

Appendix D: Plugin compatibility with Gradle Build Tool and Gradle Enterprise

Compatibility between versions of Gradle, Gradle Enterprise and the build scan plugin can be found here.