Fetch
RouterOS /tool/fetch transfers files and makes HTTP/HTTPS requests from the router itself. It supports downloading files from remote servers, uploading files (including config backups), and calling REST APIs from scripts. All four protocols are supported: HTTP, HTTPS, FTP, and SFTP.
Sub-menu
Section titled “Sub-menu”/tool fetchParameters
Section titled “Parameters”| Parameter | Default | Description |
|---|---|---|
url | — | Full URL including protocol, host, path, and optional query string |
mode | (from URL) | Override protocol: http, https, ftp, sftp |
http-method | get | HTTP method: get, post, put, delete, patch |
http-data | — | Request body payload for POST/PUT (max 64 KB) |
http-header-field | — | Custom HTTP headers as Name: Value pairs, comma-separated |
http-content-encoding | — | Compress payload before sending: gzip or deflate |
http-max-redirect-count | — | Maximum number of HTTP redirects to follow |
http-output | data | HTTP-specific output handling: data or none |
http-user-agent | — | Override the User-Agent header |
output | file | Where to place the response: file, user, user-with-headers, print, none |
dst-path | — | Local filename to write response (for output=file) |
src-path | — | Local file to upload (for upload=yes) |
upload | no | yes to upload src-path to the remote URL |
user | — | Username for FTP/SFTP authentication |
password | — | Password for FTP/SFTP authentication |
ascii | no | FTP only: use ASCII transfer mode instead of binary |
host-key | — | SFTP server host key for server identity verification |
check-certificate | no | HTTPS certificate validation: no, yes, yes-without-crl |
certificate | — | Name of a certificate in the RouterOS store to use for client auth |
as-value | — | Flag: return fetch result as a record (for script variable capture) |
Output Modes
Section titled “Output Modes”| Mode | Behavior |
|---|---|
file | Write response body to local file (dst-path) — default |
user | Store response body in script variable (max 64 KB) |
user-with-headers | Store headers + body in variable; body effectively capped at ~20 KB |
print | Print response body to terminal |
none | Discard response |
HTTP GET Requests
Section titled “HTTP GET Requests”Basic GET
Section titled “Basic GET”# Download a file/tool fetch url="https://example.com/config.rsc" dst-path="config.rsc"GET with Response in Variable
Section titled “GET with Response in Variable”Use output=user and as-value to capture the response in a script:
:local result [/tool fetch url="https://api.ipify.org/" output=user as-value]:put ($result->"data")GET with Custom Headers
Section titled “GET with Custom Headers”Separate multiple headers with commas. If a header value contains a literal comma, escape it as \,:
/tool fetch url="https://api.example.com/status" \ http-header-field="Authorization: Bearer mytoken,Accept: application/json" \ output=userGET with URL Query Parameters
Section titled “GET with URL Query Parameters”Include query parameters directly in the URL:
/tool fetch url="https://api.example.com/query?type=full&format=json" output=printHTTP POST Requests
Section titled “HTTP POST Requests”Set http-method=post and supply the request body in http-data. The Content-Type header must be set explicitly when sending structured payloads.
JSON POST
Section titled “JSON POST”/tool fetch url="https://api.example.com/events" \ http-method=post \ http-data="{\"router\":\"core1\",\"status\":\"up\"}" \ http-header-field="Content-Type: application/json" \ output=userForm-Encoded POST
Section titled “Form-Encoded POST”/tool fetch url="https://notify.example.com/alert" \ http-method=post \ http-data="host=core1&event=reboot" \ http-header-field="Content-Type: application/x-www-form-urlencoded"Webhook Notifications
Section titled “Webhook Notifications”RouterOS scripts can send event-driven alerts to any HTTP webhook endpoint — including Slack, Teams, PagerDuty, or custom monitoring systems — using a JSON POST.
Sending a Webhook Alert
Section titled “Sending a Webhook Alert”:local identity [/system identity get name]:local payload ("{\"text\":\"Router alert: WAN down on " . $identity . "\"}")/tool fetch url="https://hooks.example.com/services/T000/B000/xxxx" \ http-method=post \ http-data=$payload \ http-header-field="Content-Type: application/json" \ output=noneNetwatch-Triggered Webhook
Section titled “Netwatch-Triggered Webhook”Pair /tool fetch with Netwatch to fire a webhook whenever a host goes down or comes back up:
# Store the notifier as a named script/system script add name="notify-down" source={ /tool fetch url="https://hooks.example.com/services/T000/B000/xxxx" \ http-method=post \ http-data="{\"text\":\"8.8.8.8 is DOWN\"}" \ http-header-field="Content-Type: application/json" \ output=none}/system script add name="notify-up" source={ /tool fetch url="https://hooks.example.com/services/T000/B000/xxxx" \ http-method=post \ http-data="{\"text\":\"8.8.8.8 is UP\"}" \ http-header-field="Content-Type: application/json" \ output=none}
# Create the Netwatch probe/tool netwatch add host=8.8.8.8 interval=30s \ down-script="/system script run notify-down" \ up-script="/system script run notify-up"Scheduled Heartbeat
Section titled “Scheduled Heartbeat”Send a periodic status ping to confirm the router is reachable:
/system script add name="heartbeat" source={ :local t [/system clock get time] :local identity [/system identity get name] :local payload ("{\"text\":\"[" . $identity . "] heartbeat at " . $t . "\"}") /tool fetch url="https://hooks.example.com/services/T000/B000/xxxx" \ http-method=post \ http-data=$payload \ http-header-field="Content-Type: application/json" \ output=none}/system scheduler add name="heartbeat" interval=5m on-event="heartbeat" \ policy=read,write,testFTP Transfers
Section titled “FTP Transfers”Credentials can be embedded in the URL or passed as separate user= and password= parameters.
FTP Download
Section titled “FTP Download”/tool fetch url="ftp://192.0.2.10/backups/router.backup" \ user="ftpuser" password="ftppass" \ dst-path="router.backup"FTP Upload
Section titled “FTP Upload”/tool fetch url="ftp://192.0.2.10/incoming/router.backup" \ user="ftpuser" password="ftppass" \ upload=yes src-path="router.backup"Use ascii=no (the default) for binary files such as .backup archives. Use ascii=yes only for plain text files when the remote server requires ASCII mode.
SFTP Transfers
Section titled “SFTP Transfers”SFTP uses the same upload/src-path/dst-path conventions as FTP. For security, pin the server’s host key with host-key=.
SFTP Download
Section titled “SFTP Download”/tool fetch url="sftp://198.51.100.20/home/backup/router.backup" \ user="sftpuser" password="sftppass" \ dst-path="router.backup"SFTP Upload with Host Key Pinning
Section titled “SFTP Upload with Host Key Pinning”/tool fetch url="sftp://198.51.100.20/upload/router.backup" \ user="sftpuser" password="sftppass" \ upload=yes src-path="router.backup" \ host-key="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI..."Omitting host-key= skips server identity verification — acceptable in trusted networks, but avoid it over untrusted links.
HTTPS and SSL Certificates
Section titled “HTTPS and SSL Certificates”By default, /tool/fetch does not validate TLS certificates (check-certificate=no). Enable validation for production use.
| Value | Behaviour |
|---|---|
no | No certificate validation (default) |
yes | Validate chain and CRL |
yes-without-crl | Validate chain, skip CRL check |
Use yes-without-crl when the CA’s CRL endpoint is unreachable from the router.
Importing a CA Certificate
Section titled “Importing a CA Certificate”Before check-certificate=yes will work, import the issuing CA into the RouterOS certificate store and mark it trusted:
/certificate import file-name=ca.pem/certificate set [find where name~"ca"] trusted=yesVerified HTTPS Fetch
Section titled “Verified HTTPS Fetch”/tool fetch url="https://example.com/file.txt" \ check-certificate=yes \ dst-path="file.txt"If certificate validation fails, ensure:
- The system clock is set correctly (
/system clock print) - The CA certificate and any intermediates are imported
- Each CA certificate has
trusted=yes
Config Backup and Upload Script
Section titled “Config Backup and Upload Script”A common pattern is to generate a config export or binary backup and upload it to a remote server. Run this as a scheduled script for automated daily backups.
# Automated backup + SFTP upload:local id [/system identity get name]:local d [/system clock get date]:local t [/system clock get time]
# Build a datestamp string: YYYY-MM-DD_HH-MM-SS:local ds ([:pick $d 7 11] . "-" . [:pick $d 0 3] . "-" . [:pick $d 4 6]):local ts ([:pick $t 0 2] . "-" . [:pick $t 3 5] . "-" . [:pick $t 6 8]):local fn ($id . "_" . $ds . "_" . $ts)
# Generate text export/export terse show-sensitive file=($fn . ".rsc")# Generate binary backup/system backup save name=$fn
:delay 3
# Upload both files/tool fetch url=("sftp://198.51.100.20/backups/" . $fn . ".rsc") \ upload=yes src-path=($fn . ".rsc") \ user="backupuser" password="backuppass"
/tool fetch url=("sftp://198.51.100.20/backups/" . $fn . ".backup") \ upload=yes src-path=($fn . ".backup") \ user="backupuser" password="backuppass"Schedule the Backup
Section titled “Schedule the Backup”/system scheduler add \ name="daily-backup-upload" \ start-time=03:00:00 \ interval=1d \ on-event="/system script run backup-upload" \ policy=read,write,ftp,password,sensitiveStore the backup script body in /system script with name backup-upload.
Downloading Files from External Services
Section titled “Downloading Files from External Services”RouterOS Package Download
Section titled “RouterOS Package Download”Download a .npk package from your own update mirror and install it on next reboot:
:local pkg "routeros-arm64-7.16.2.npk"/tool fetch url=("https://updates.example.net/ros/" . $pkg) \ dst-path=$pkg \ check-certificate=yes/system rebootAuthenticated Download
Section titled “Authenticated Download”Fetch from a private artifact store using a Bearer token:
/tool fetch url="https://artifacts.example.net/api/v1/files/job.rsc" \ http-header-field="Authorization: Bearer <TOKEN>" \ check-certificate=yes \ dst-path="job.rsc"Download and Import a Script
Section titled “Download and Import a Script”/tool fetch url="https://example.com/scripts/watchdog.rsc" \ check-certificate=yes dst-path="watchdog.rsc"/import file-name=watchdog.rscInspect downloaded script files before importing them. Verify the source and check the file contents with /file print or Winbox file browser.
Polling an API from a Script
Section titled “Polling an API from a Script”Use output=user with as-value to read a small JSON or text response into a variable:
:local r [/tool fetch url="https://api.example.com/device/status" \ http-header-field="Authorization: Bearer <TOKEN>" \ output=user as-value]
:local body ($r->"data"):log info ("API response: " . $body)The user output mode accepts up to 64 KB. Use user-with-headers to also capture HTTP response headers (body then limited to ~20 KB).
File Automation
Section titled “File Automation”Automated Config Update from Central Server
Section titled “Automated Config Update from Central Server”Pull a configuration script from a central server on a schedule and apply it:
/system script add name="apply-config-update" source={ /tool fetch url="https://config.example.net/routers/core1.rsc" \ check-certificate=yes \ dst-path="update.rsc" # Verify file was downloaded before importing :if ([:len [/file find name="update.rsc"]] > 0) do={ /import file-name=update.rsc /file remove "update.rsc" }}/system scheduler add name="config-sync" start-time=02:00:00 interval=1d \ on-event="/system script run apply-config-update" \ policy=read,write,ftp,policy,password,sensitiveAlways inspect scripts before importing. Download to a test environment first and review the file contents with /file print or the Winbox file browser.
Troubleshooting
Section titled “Troubleshooting”| Symptom | Likely Cause | Fix |
|---|---|---|
TLS handshake failed | Certificate not trusted or clock wrong | Check system time; import and trust CA |
no such item on as-value | Fetch failed silently | Add output=print temporarily to see error |
| Upload writes empty file | src-path file does not exist | Verify with /file print before running fetch |
FTP returns permission denied | Incorrect credentials or path | Verify user=, password=, and remote path |
| SFTP host key mismatch | Server key changed | Update host-key= to new server key |