library(epwshiftr)

workflow_root <- file.path(tempdir(), "epwshiftr-downloader")
if (dir.exists(workflow_root)) {
    unlink(workflow_root, recursive = TRUE)
}
dir.create(workflow_root, recursive = TRUE, showWarnings = FALSE)

options(
    epwshiftr.dir_cache = file.path(workflow_root, "cache")
)

select_cols <- function(x, cols, n = 10L) {
    x <- data.table::as.data.table(x)
    keep <- intersect(cols, names(x))
    if (length(keep)) {
        x <- x[, keep, with = FALSE]
    }
    utils::head(x, n)
}

Downloader is the transfer engine used by shift_download(), EsgStore$download_files(), and the command line interface. It is also a general downloader: a plan only needs logical_file_id, filename, and url columns. ESGF-specific columns such as file_key, dataset_id, service, or data_node enrich the manifest but are not required for ordinary HTTPS files.

The main future EPW workflow usually avoids full NetCDF downloads because shift_extract() reads through OPeNDAP first. Use the downloader when you intentionally need local files, offline work, repeated extraction, resumable transfers, background jobs, or operational visibility.

Create a Persistent Downloader

Use a persistent manifest when you want resumable sessions, task status, event logs, background jobs, node history, and typed transfer configuration.

download_root <- file.path(workflow_root, "general-downloads")

downloader <- Downloader$new(
    dest = file.path(download_root, "files"),
    temp = file.path(download_root, "tmp"),
    manifest = file.path(download_root, "manifest.duckdb"),
    retries = 2L,
    timeout = 120L,
    connect_timeout = 30L,
    n_workers = 2L,
    resource_policy = list(
        disk_preflight = TRUE,
        min_free_space = 0
    )
)

downloader
downloader$manifest
#> [1] "/var/folders/8f/t8sk2pps6135xbp47cs8qb2r0000gn/T//Rtmp3Hed7X/epwshiftr-downloader/general-downloads/manifest.duckdb"

The manifest stores configuration, sessions, tasks, candidate URLs, transfer events, background jobs, daemon state, control messages, and data-node history.

Download One File Directly

download() is the shortcut API for a single URL. It can run without a persistent session, but using it on the same downloader keeps the destination, temporary directory, retry, timeout, and checksum behavior consistent.

single_path <- downloader$download(
    url = "https://raw.githubusercontent.com/r-lib/actions/v2/README.md",
    filename = "r-lib-actions-readme.md",
    subdir = "single",
    progress = FALSE,
    overwrite = FALSE,
    resume = TRUE
)

single_path
#> [1] "/private/var/folders/8f/t8sk2pps6135xbp47cs8qb2r0000gn/T/Rtmp3Hed7X/epwshiftr-downloader/general-downloads/files/single/r-lib-actions-readme.md"
file.info(single_path)[, c("size", "mtime")]
#>                                                                                                                                                 size
#> /private/var/folders/8f/t8sk2pps6135xbp47cs8qb2r0000gn/T/Rtmp3Hed7X/epwshiftr-downloader/general-downloads/files/single/r-lib-actions-readme.md 8700
#>                                                                                                                                                               mtime
#> /private/var/folders/8f/t8sk2pps6135xbp47cs8qb2r0000gn/T/Rtmp3Hed7X/epwshiftr-downloader/general-downloads/files/single/r-lib-actions-readme.md 2026-06-25 02:14:07
readLines(single_path, n = 6L)
#> [1] "# GitHub Actions for the R language"
#> [2] ""
#> [3] "[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/8907/badge)](https://www.bestpractices.dev/projects/8907)"
#> [4] "[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/r-lib/actions/badge)](https://securityscorecards.dev/viewer/?uri=github.com/r-lib/actions)"
#> [5] "[![R build status](https://github.com/r-lib/actions/workflows/R-CMD-check/badge.svg)](https://github.com/r-lib/actions/actions?workflow=R-CMD-check)"
#> [6] "[![RStudio community](https://img.shields.io/badge/community-github--actions-blue?style=social&logo=rstudio&logoColor=75AADB)](https://community.rstudio.com/new-topic?category=Package%20development&tags=github-actions)"

Enqueue a General Download Plan

A persistent plan can contain multiple URLs and candidate mirrors. The minimal required columns are logical_file_id, filename, and url; subdir, checksum, checksum_type, size, service, and data_node are optional.

This live example downloads several small HTTPS files into the article-local temporary directory.

small_plan <- data.frame(
    logical_file_id = c(
        "r-lib-setup-r",
        "r-lib-setup-r-dependencies",
        "r-lib-check-r-package"
    ),
    filename = c(
        "setup-r-action.yml",
        "setup-r-dependencies-action.yaml",
        "check-r-package-action.yaml"
    ),
    subdir = "batch",
    url = c(
        "https://raw.githubusercontent.com/r-lib/actions/v2/setup-r/action.yml",
        "https://raw.githubusercontent.com/r-lib/actions/v2/setup-r-dependencies/action.yaml",
        "https://raw.githubusercontent.com/r-lib/actions/v2/check-r-package/action.yaml"
    ),
    checksum = NA_character_,
    checksum_type = "sha256",
    size = NA_real_,
    service = "HTTPS",
    data_node = "raw.githubusercontent.com",
    stringsAsFactors = FALSE
)

select_cols(small_plan, c("logical_file_id", "filename", "subdir", "url", "service", "data_node"))
#>               logical_file_id                         filename subdir
#>                        <char>                           <char> <char>
#> 1:              r-lib-setup-r               setup-r-action.yml  batch
#> 2: r-lib-setup-r-dependencies setup-r-dependencies-action.yaml  batch
#> 3:      r-lib-check-r-package      check-r-package-action.yaml  batch
#>                                                                                    url
#>                                                                                 <char>
#> 1:               https://raw.githubusercontent.com/r-lib/actions/v2/setup-r/action.yml
#> 2: https://raw.githubusercontent.com/r-lib/actions/v2/setup-r-dependencies/action.yaml
#> 3:      https://raw.githubusercontent.com/r-lib/actions/v2/check-r-package/action.yaml
#>    service                 data_node
#>     <char>                    <char>
#> 1:   HTTPS raw.githubusercontent.com
#> 2:   HTTPS raw.githubusercontent.com
#> 3:   HTTPS raw.githubusercontent.com

Preflight is read-only. It estimates task count, known byte requirements, free space, and whether disk preflight would block the run.

downloader$preflight(plan = small_plan)
#>   task_count needs_download required_bytes size_unknown_count dest_free_bytes
#> 1          3              3              0                  3    298211315712
#>   tmp_free_bytes min_free_space dest_disk_ok tmp_disk_ok disk_ok
#> 1   298211315712              0         TRUE        TRUE      NA
#>   disk_would_block disk_preflight
#> 1            FALSE           TRUE

Enqueue writes a session, tasks, and candidates to the manifest. It does not download until run() is called.

session_id <- downloader$enqueue(
    small_plan,
    session_label = "small-live-files"
)

downloader$sessions()
#>                 session_id            label status          created_at
#> 1 20260624-181407-0d0cb568 small-live-files queued 2026-06-24 18:14:07
#>            updated_at completed_at
#> 1 2026-06-24 18:14:07         <NA>
select_cols(downloader$tasks(session_id = session_id), c(
    "task_id", "logical_file_id", "filename", "status",
    "target_path", "size"
), n = 6L)
#>                                                             task_id
#>                                                              <char>
#> 1: 4daf72ca754d11bc2e55dc3f372d2045b448d358c070b59da56a7e11af457e04
#> 2: 58534ff425504fe4271b159646fbdb17c4311cc742add3116da3e81656111269
#> 3: bc9b902b34cf54a38362043d473288417182d98dab7400dbf39ac28908d646e9
#>               logical_file_id                         filename status
#>                        <char>                           <char> <char>
#> 1:      r-lib-check-r-package      check-r-package-action.yaml queued
#> 2: r-lib-setup-r-dependencies setup-r-dependencies-action.yaml queued
#> 3:              r-lib-setup-r               setup-r-action.yml queued
#>                                                                                                                                                target_path
#>                                                                                                                                                     <char>
#> 1:      /private/var/folders/8f/t8sk2pps6135xbp47cs8qb2r0000gn/T/Rtmp3Hed7X/epwshiftr-downloader/general-downloads/files/batch/check-r-package-action.yaml
#> 2: /private/var/folders/8f/t8sk2pps6135xbp47cs8qb2r0000gn/T/Rtmp3Hed7X/epwshiftr-downloader/general-downloads/files/batch/setup-r-dependencies-action.yaml
#> 3:               /private/var/folders/8f/t8sk2pps6135xbp47cs8qb2r0000gn/T/Rtmp3Hed7X/epwshiftr-downloader/general-downloads/files/batch/setup-r-action.yml
#>     size
#>    <num>
#> 1:    NA
#> 2:    NA
#> 3:    NA

run_rows <- downloader$run(
    session_id = session_id,
    progress = FALSE,
    overwrite = FALSE,
    resume = TRUE
)

select_cols(run_rows, c(
    "logical_file_id", "filename", "status",
    "bytes_done", "target_path", "selected_url"
), n = 6L)
#>               logical_file_id                         filename status
#>                        <char>                           <char> <char>
#> 1:      r-lib-check-r-package      check-r-package-action.yaml   done
#> 2: r-lib-setup-r-dependencies setup-r-dependencies-action.yaml   done
#> 3:              r-lib-setup-r               setup-r-action.yml   done
#>    bytes_done
#>         <num>
#> 1:       4031
#> 2:      15578
#> 3:       4260
#>                                                                                                                                                target_path
#>                                                                                                                                                     <char>
#> 1:      /private/var/folders/8f/t8sk2pps6135xbp47cs8qb2r0000gn/T/Rtmp3Hed7X/epwshiftr-downloader/general-downloads/files/batch/check-r-package-action.yaml
#> 2: /private/var/folders/8f/t8sk2pps6135xbp47cs8qb2r0000gn/T/Rtmp3Hed7X/epwshiftr-downloader/general-downloads/files/batch/setup-r-dependencies-action.yaml
#> 3:               /private/var/folders/8f/t8sk2pps6135xbp47cs8qb2r0000gn/T/Rtmp3Hed7X/epwshiftr-downloader/general-downloads/files/batch/setup-r-action.yml
#>                                                                           selected_url
#>                                                                                 <char>
#> 1:      https://raw.githubusercontent.com/r-lib/actions/v2/check-r-package/action.yaml
#> 2: https://raw.githubusercontent.com/r-lib/actions/v2/setup-r-dependencies/action.yaml
#> 3:               https://raw.githubusercontent.com/r-lib/actions/v2/setup-r/action.yml

Inspect Sessions, Tasks, Events, and Files

The manifest is useful after the R session that started the download has gone away. It records what was queued, what completed, and which URL was selected.

downloader$sessions()
#>                 session_id            label status          created_at
#> 1 20260624-181407-0d0cb568 small-live-files   done 2026-06-24 18:14:07
#>            updated_at        completed_at
#> 1 2026-06-24 18:14:11 2026-06-24 18:14:11

select_cols(downloader$status(session_id = session_id), c(
    "logical_file_id", "status", "bytes_done", "target_path",
    "selected_url", "last_error"
), n = 10L)
#>               logical_file_id status bytes_done
#>                        <char> <char>      <num>
#> 1:      r-lib-check-r-package   done       4031
#> 2: r-lib-setup-r-dependencies   done      15578
#> 3:              r-lib-setup-r   done       4260
#>                                                                                                                                                target_path
#>                                                                                                                                                     <char>
#> 1:      /private/var/folders/8f/t8sk2pps6135xbp47cs8qb2r0000gn/T/Rtmp3Hed7X/epwshiftr-downloader/general-downloads/files/batch/check-r-package-action.yaml
#> 2: /private/var/folders/8f/t8sk2pps6135xbp47cs8qb2r0000gn/T/Rtmp3Hed7X/epwshiftr-downloader/general-downloads/files/batch/setup-r-dependencies-action.yaml
#> 3:               /private/var/folders/8f/t8sk2pps6135xbp47cs8qb2r0000gn/T/Rtmp3Hed7X/epwshiftr-downloader/general-downloads/files/batch/setup-r-action.yml
#>                                                                           selected_url
#>                                                                                 <char>
#> 1:      https://raw.githubusercontent.com/r-lib/actions/v2/check-r-package/action.yaml
#> 2: https://raw.githubusercontent.com/r-lib/actions/v2/setup-r-dependencies/action.yaml
#> 3:               https://raw.githubusercontent.com/r-lib/actions/v2/setup-r/action.yml
#>    last_error
#>        <char>
#> 1:       <NA>
#> 2:       <NA>
#> 3:       <NA>

select_cols(downloader$events(session_id = session_id), c(
    "event", "message", "task_id", "created_at"
), n = 12L)
#>           event
#>          <char>
#> 1:      enqueue
#> 2:        start
#> 3:        start
#> 4:         done
#> 5:        start
#> 6:         done
#> 7: session_done
#> 8:         done
#>                                                                                                                                                    message
#>                                                                                                                                                     <char>
#> 1:                                                                                                                              Queued 3 download task(s).
#> 2:                                                                          https://raw.githubusercontent.com/r-lib/actions/v2/check-r-package/action.yaml
#> 3:                                                                     https://raw.githubusercontent.com/r-lib/actions/v2/setup-r-dependencies/action.yaml
#> 4:      /private/var/folders/8f/t8sk2pps6135xbp47cs8qb2r0000gn/T/Rtmp3Hed7X/epwshiftr-downloader/general-downloads/files/batch/check-r-package-action.yaml
#> 5:                                                                                   https://raw.githubusercontent.com/r-lib/actions/v2/setup-r/action.yml
#> 6: /private/var/folders/8f/t8sk2pps6135xbp47cs8qb2r0000gn/T/Rtmp3Hed7X/epwshiftr-downloader/general-downloads/files/batch/setup-r-dependencies-action.yaml
#> 7:                                                                                                                                                    done
#> 8:               /private/var/folders/8f/t8sk2pps6135xbp47cs8qb2r0000gn/T/Rtmp3Hed7X/epwshiftr-downloader/general-downloads/files/batch/setup-r-action.yml
#>                                                             task_id
#>                                                              <char>
#> 1:                                                             <NA>
#> 2: 4daf72ca754d11bc2e55dc3f372d2045b448d358c070b59da56a7e11af457e04
#> 3: 58534ff425504fe4271b159646fbdb17c4311cc742add3116da3e81656111269
#> 4: 4daf72ca754d11bc2e55dc3f372d2045b448d358c070b59da56a7e11af457e04
#> 5: bc9b902b34cf54a38362043d473288417182d98dab7400dbf39ac28908d646e9
#> 6: 58534ff425504fe4271b159646fbdb17c4311cc742add3116da3e81656111269
#> 7:                                                             <NA>
#> 8: bc9b902b34cf54a38362043d473288417182d98dab7400dbf39ac28908d646e9
#>             created_at
#>                 <POSc>
#> 1: 2026-06-24 18:14:07
#> 2: 2026-06-24 18:14:08
#> 3: 2026-06-24 18:14:08
#> 4: 2026-06-24 18:14:10
#> 5: 2026-06-24 18:14:10
#> 6: 2026-06-24 18:14:10
#> 7: 2026-06-24 18:14:11
#> 8: 2026-06-24 18:14:11

list.files(file.path(download_root, "files"), recursive = TRUE)
#> [1] "batch/check-r-package-action.yaml"
#> [2] "batch/setup-r-action.yml"
#> [3] "batch/setup-r-dependencies-action.yaml"
#> [4] "single/r-lib-actions-readme.md"

verify() checks completed files. When a task has no checksum, successful file existence is enough. When a checksum exists, the recorded algorithm is used.

select_cols(downloader$verify(session_id = session_id), c(
    "logical_file_id", "status", "checksum_ok", "target_path"
), n = 10L)
#>               logical_file_id status checksum_ok
#>                        <char> <char>      <lgcl>
#> 1:      r-lib-check-r-package   done        TRUE
#> 2: r-lib-setup-r-dependencies   done        TRUE
#> 3:              r-lib-setup-r   done        TRUE
#>                                                                                                                                                target_path
#>                                                                                                                                                     <char>
#> 1:      /private/var/folders/8f/t8sk2pps6135xbp47cs8qb2r0000gn/T/Rtmp3Hed7X/epwshiftr-downloader/general-downloads/files/batch/check-r-package-action.yaml
#> 2: /private/var/folders/8f/t8sk2pps6135xbp47cs8qb2r0000gn/T/Rtmp3Hed7X/epwshiftr-downloader/general-downloads/files/batch/setup-r-dependencies-action.yaml
#> 3:               /private/var/folders/8f/t8sk2pps6135xbp47cs8qb2r0000gn/T/Rtmp3Hed7X/epwshiftr-downloader/general-downloads/files/batch/setup-r-action.yml

downloader$cleanup_tmp(all = TRUE)
#> [1] 0

Retry and resume become important after interrupted jobs, failed checksums, cancelled tasks, or a process exit during transfer. In a successful article run there is nothing to requeue, so the operational calls are shown here without executing them:

downloader$retry(session_id = session_id)
downloader$resume(session_id = session_id, progress = TRUE)
downloader$cancel(session_id = session_id)

Background Jobs and Daemon Mode

Long-running sessions can be submitted in the background. The job itself is stored in the manifest, and logs are written next to the manifest.

job <- downloader$start(
    session_id = session_id,
    overwrite = FALSE,
    resume = TRUE,
    mode = "process"
)

downloader$jobs()
downloader$job_status(job$job_id)
downloader$job_logs(job$job_id, tail = 50L)
downloader$stop_job(job$job_id)

Daemon mode keeps a persistent downloader loop alive for repeated submissions:

downloader$daemon_start(port = 0L, heartbeat_interval = 5)
downloader$daemon_status()
downloader$start(session_id = session_id, mode = "daemon")
downloader$daemon_stop()

Those examples are intentionally shown as ordinary code snippets instead of executed article chunks because starting detached processes during documentation builds can leave local background work behind.

Generate an ESGF Download Plan

ESGF File results produce downloader-ready plans with service URLs, candidate ranking fields, file keys, sizes, checksums, and data-node metadata. This live example builds an ESGF plan but does not download the large NetCDF files.

esgf_query <- esg_query("https://esgf-data.dkrz.de")$
    activity_id("ScenarioMIP")$
    experiment_id("ssp585")$
    source_id("MPI-ESM1-2-LR")$
    variant_label("r1i1p1f1")$
    frequency("mon")$
    variable_id("tas")$
    data_node("esgf.ceda.ac.uk")$
    params(table_id = "Amon")$
    limit(3L)

esgf_files <- esgf_query$collect(
    type = "File",
    fields = "*",
    all = FALSE,
    limit = TRUE
)

if (!esgf_files$count()) {
    stop("The live ESGF query returned no File records.", call. = FALSE)
}

esgf_files_2060 <- esgf_files$filter_time(
    "2060-01-01T00:00:00Z",
    "2060-12-31T23:59:59Z",
    method = "drs"
)

if (!esgf_files_2060$count()) {
    stop("The live ESGF query returned no File records covering 2060.", call. = FALSE)
}

esgf_files_2060$count()
#> [1] 1
esgf_plan <- esgf_files_2060$download_plan(
    replica = "current",
    service = "HTTPServer",
    probe = FALSE,
    strategy = "stable"
)

select_cols(esgf_plan, c(
    "logical_file_id", "filename", "service", "data_node",
    "size", "url", "checksum", "checksum_type"
), n = 10L)
#>                                                                                                                        logical_file_id
#>                                                                                                                                 <char>
#> 1: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.tas.gn.tas_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_205501-207412.nc
#>                                                      filename    service
#>                                                        <char>     <char>
#> 1: tas_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_205501-207412.nc HTTPServer
#>          data_node    size
#>             <char>   <num>
#> 1: esgf.ceda.ac.uk 8011675
#>                                                                                                                                                                                            url
#>                                                                                                                                                                                         <char>
#> 1: https://esgf.ceda.ac.uk/thredds/fileServer/esg_cmip6/CMIP6/ScenarioMIP/MPI-M/MPI-ESM1-2-LR/ssp585/r1i1p1f1/Amon/tas/gn/v20190710/tas_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_205501-207412.nc
#>                                                            checksum
#>                                                              <char>
#> 1: f1419fb9621b49e5bde363dd2d79c27f63d692ff3e7a2b81a5910fb5356f3294
#>    checksum_type
#>           <char>
#> 1:        sha256

probe = FALSE keeps this article fast and avoids touching candidate URLs just to rank them. In operational runs, probe = TRUE can record latency and availability in the downloader’s download_node table.

Use a Store-Bound Downloader

For store-managed ESGF work, prefer store$downloader(). The downloader manifest, temporary files, final files, and logs then live under the store, and completed tasks can be synced back into the store catalog.

store <- EsgStore$new(file.path(workflow_root, "store"))
store_query_id <- store$add_query(
    esgf_query,
    label = "tas-ssp585-2060-plan",
    track = TRUE
)

store_downloader <- store$downloader(
    n_workers = 2L,
    retries = 1L,
    timeout = 120L,
    resource_policy = list(min_free_space = 0)
)

preflight <- store$download_preflight(
    query_id = store_query_id,
    downloader = store_downloader,
    replica = "current",
    service = "HTTPServer",
    probe = FALSE,
    all = FALSE,
    limit = TRUE
)

preflight$summary
#>                                                            query_id
#>                                                              <char>
#> 1: d31b46c91e03aa9eb71ac76be90cd1dcaebc742db41b1a3485d426a8ecb82f6c
#>                   label file_total current_count candidate_count bytes_total
#>                  <char>      <int>         <int>           <int>       <num>
#> 1: tas-ssp585-2060-plan          3             3               3    24059358
#>    local_available needs_download no_httpserver cooldown_nodes
#>              <int>          <int>         <int>          <int>
#> 1:               0              3             0              0
#>    target_path_collision_count missing_layout_field_count required_bytes
#>                          <int>                      <int>          <num>
#> 1:                           0                          0       24059358
#>    size_unknown_count dest_free_bytes tmp_free_bytes min_free_space disk_ok
#>                 <int>           <num>          <num>          <num>  <lgcl>
#> 1:                  0    298203377664   298203377664              0    TRUE
#>    disk_would_block disk_preflight
#>              <lgcl>         <lgcl>
#> 1:            FALSE           TRUE
select_cols(preflight$files, c(
    "file_key", "filename", "variable_id", "size", "local_path", "status"
), n = 10L)
#>                                                                                                                               file_key
#>                                                                                                                                 <char>
#> 1: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.tas.gn.tas_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_201501-203412.nc
#> 2: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.tas.gn.tas_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_203501-205412.nc
#> 3: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.tas.gn.tas_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_205501-207412.nc
#>                                                      filename variable_id
#>                                                        <char>      <char>
#> 1: tas_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_201501-203412.nc         tas
#> 2: tas_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_203501-205412.nc         tas
#> 3: tas_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_205501-207412.nc         tas
#>       size local_path  status
#>      <num>     <char>  <char>
#> 1: 8025316       <NA> current
#> 2: 8022367       <NA> current
#> 3: 8011675       <NA> current
select_cols(preflight$candidates, c(
    "filename", "service", "data_node", "size", "url"
), n = 10L)
#>                                                      filename    service
#>                                                        <char>     <char>
#> 1: tas_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_201501-203412.nc HTTPServer
#> 2: tas_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_203501-205412.nc HTTPServer
#> 3: tas_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_205501-207412.nc HTTPServer
#>          data_node    size
#>             <char>   <num>
#> 1: esgf.ceda.ac.uk 8025316
#> 2: esgf.ceda.ac.uk 8022367
#> 3: esgf.ceda.ac.uk 8011675
#>                                                                                                                                                                                            url
#>                                                                                                                                                                                         <char>
#> 1: https://esgf.ceda.ac.uk/thredds/fileServer/esg_cmip6/CMIP6/ScenarioMIP/MPI-M/MPI-ESM1-2-LR/ssp585/r1i1p1f1/Amon/tas/gn/v20190710/tas_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_201501-203412.nc
#> 2: https://esgf.ceda.ac.uk/thredds/fileServer/esg_cmip6/CMIP6/ScenarioMIP/MPI-M/MPI-ESM1-2-LR/ssp585/r1i1p1f1/Amon/tas/gn/v20190710/tas_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_203501-205412.nc
#> 3: https://esgf.ceda.ac.uk/thredds/fileServer/esg_cmip6/CMIP6/ScenarioMIP/MPI-M/MPI-ESM1-2-LR/ssp585/r1i1p1f1/Amon/tas/gn/v20190710/tas_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_205501-207412.nc

To actually enqueue and run those ESGF downloads, use:

session_id <- store$download_query(
    query_id = store_query_id,
    downloader = store_downloader,
    replica = "current",
    service = "HTTPServer",
    probe = TRUE,
    run = TRUE,
    progress = TRUE
)

store$sync_downloads(store_downloader)

For command-line operation, see CLI operations. For how query records, downloads, extraction outputs, and artifacts are tied together, see ESG stores.