---
title: Running a webserver in your Actor
sidebar_label: Running a webserver
---

Each Actor run on the Apify platform is assigned a unique hard-to-guess URL (for example `https://8segt5i81sokzm.runs.apify.net`),
which enables HTTP access to an optional web server running inside the Actor run's container.

The URL is available in the following places:

- In Apify Console, on the Actor run details page as the **Container URL** field.
- In the API as the `containerUrl` property of the [Run object](https://docs.apify.com/api/v2#/reference/actors/run-object/get-run).
- In the Actor as the `Actor.config.container_url` property.

The web server running inside the container must listen at the port defined by the `Actor.config.container_port` property.
When running Actors locally, the port defaults to `4321`,
so the web server will be accessible at `http://localhost:4321`.

## Example

The following example demonstrates how to start a simple web server in your Actor,
which will respond to every GET request with the number of items that the Actor has processed so far:

```python title="src/main.py"
import asyncio
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer

from apify import Actor

processed_items = 0
http_server = None

# Just a simple handler that will print the number of processed items so far
# on every GET request
class RequestHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.log_request()
        self.send_response(200)
        self.end_headers()
        self.wfile.write(bytes(f'Processed items: {processed_items}', encoding='utf-8'))

def run_server():
    # Start the HTTP server on the provided port,
    # and save a reference to the server
    global http_server
    with ThreadingHTTPServer(('', Actor.config.container_port), RequestHandler) as server:
        Actor.log.info(f'Server running on {Actor.config.container_url}')
        http_server = server
        server.serve_forever()

async def main():
    global processed_items
    async with Actor:
        # Start the HTTP server in a separate thread
        run_server_task = asyncio.get_running_loop().run_in_executor(None, run_server)

        # Simulate doing some work
        for _ in range(100):
            await asyncio.sleep(1)
            processed_items += 1
            Actor.log.info(f'Processed items: {processed_items}')

        # Signal the HTTP server to shut down, and wait for it to finish
        http_server.shutdown()
        await run_server_task
```
