diff --git a/scripts/larvatagger b/scripts/larvatagger
index 5a0a65aed7cc2f537d6e5701784cba00852c3d00..c6007ad05c627fae96f6706abe230f56d1bcdaf0 100755
--- a/scripts/larvatagger
+++ b/scripts/larvatagger
@@ -52,7 +52,7 @@ import|merge|--version|-V)
 LarvaTagger
 
 Usage:
-  larvatagger open [<file-path>] [--backends=<path>] [--port=<number>] [--quiet] [--viewer] [--browser] [--view-factor=<real>] [--manual-label=<label>]
+  larvatagger open [<file-path>] [--backends=<path>] [--port=<number>] [--server-url=<url>] [--quiet] [--viewer] [--browser] [--view-factor=<real>] [--manual-label=<label>]
   larvatagger import <input-path> [<output-file>] [--id=<id>] [--framerate=<fps>] [--pixelsize=<μm>] [--overrides=<comma-separated-list>] [--default-label=<label>] [--manual-label=<label>] [--decode] [--copy-labels]
   larvatagger train <backend-path> <data-path> <model-instance> [--pretrained-model=<instance>] [--labels=<comma-separated-list>] [--sample-size=<N>] [--balancing-strategy=<strategy>] [--class-weights=<csv>] [--manual-label=<label>] [--layers=<N>] [--iterations=<N>] [--seed=<seed>] [--debug]
   larvatagger train <backend-path> <data-path> <model-instance> --fine-tune=<instance> [--balancing-strategy=<strategy>] [--manual-label=<label>] [--iterations=<N>] [--seed=<seed>] [--debug]
@@ -71,6 +71,7 @@ Options:
   --pixelsize=<μm>      Camera pixel size, in micrometers.
   --backends=<path>     Path to backend repository.
   --port=<number>       Port number the server listens to.
+  --server-url=<url>    Server address, for remote access.
   --viewer              Disable editing capabilities.
   --browser             Automatically open a browser tab at the served location.
   --view-factor=<real>  Scaling factor for the larva views; default is 2 on macOS, 1 elsewhere.
@@ -104,6 +105,8 @@ Commands:
     The optional positional argument <file-path> can also be the data root directory.
     Backends defined in LarvaTagger project root directory are automatically found. Other
     backend locations can be specified with the --backends argument.
+    By default, if --server-url is specified, the port is appended to the ip address or
+    domain name. To prevent this behavior, include the desired port number in the url.
 
   import    Generate a label file and store metadata.
 
diff --git a/src/cli_open.jl b/src/cli_open.jl
index 56ab8b563ed874cd35e429b3623872a417399aea..a1d46b678e4e4faf1b2790a1202297a6b354ca0e 100644
--- a/src/cli_open.jl
+++ b/src/cli_open.jl
@@ -9,7 +9,7 @@ export main
 usage = """LarvaTagger.jl - launch the server-based GUI.
 
 Usage:
-  larvatagger-gui.jl [<file-path>] [--backends=<path>] [--port=<number>] [--quiet] [--viewer] [--browser] [--view-factor=<real>] [--manual-label=<label>]
+  larvatagger-gui.jl [<file-path>] [--backends=<path>] [--port=<number>] [--server-url=<url>] [--quiet] [--viewer] [--browser] [--view-factor=<real>] [--manual-label=<label>]
   larvatagger-gui.jl -h | --help
 
 Options:
@@ -17,6 +17,7 @@ Options:
   -q --quiet              Do not show instructions.
   --backends=<path>       Path to backend repository.
   --port=<number>         Port number the server listens to.
+  --server-url=<url>      Server address, for remote access.
   --viewer                Disable editing capabilities.
   --browser               Automatically open a browser tab at the served location.
   --view-factor=<real>    Scaling factor for the larva views; default is 2 on macOS, 1 elsewhere.
@@ -25,6 +26,9 @@ Options:
 The optional positional argument <file-path> can also be the data root directory.
 Backends defined in LarvaTagger project root directory are automatically found. Other
 backend locations can be specified with the --backends argument.
+
+By default, if --server-url is specified, the port is appended to the ip address or domain
+name. To prevent this behavior, include the desired port number in the url.
 """
 
 function main(args=ARGS; exit_on_error=false)
@@ -82,12 +86,30 @@ function main(args=ARGS; exit_on_error=false)
     #
     port = parsed_args["--port"]
     port = isnothing(port) ? 9284 : parse(Int, port)
-    server = Server(app, "0.0.0.0", port)
+    proxy_url = parsed_args["--server-url"]
+    if isnothing(proxy_url)
+        proxy_url = ""
+    elseif !startswith(proxy_url, "http")
+        proxy_url = "http://$(proxy_url)"
+    end
+    server = Server(app, "0.0.0.0", port; proxy_url=proxy_url)
+    port = server.port
+    if !isempty(proxy_url)
+        protocol, remainder = split(proxy_url, "://")
+        if !(':' in remainder)
+            server.proxy_url = proxy_url = if '/' in remainder
+                server_name, path = split(remainder, '/'; limit=2)
+                "$(protocol)://$(server_name):$(port)/$(path)"
+            else
+                "$(protocol)://$(remainder):$(port)"
+            end
+        end
+    end
     if parsed_args["--browser"]
         Bonito.HTTPServer.openurl("http://127.0.0.1:$(port)")
     end
     if verbose
-        @info "The server is ready at http://127.0.0.1:$(port)"
+        @info "The server is ready at $(Bonito.HTTPServer.online_url(server, ""))"
     end
     if verbose
         @info "Press Ctrl+D to stop the server (or Ctrl+C if in PowerShell)"