Skip to main content
Version: 1.7

Running webserver

In this guide, you'll learn how to run a web server inside your Apify Actor. This is useful for monitoring Actor progress, creating custom APIs, or serving content during the Actor run.

Introduction

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.
  • 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 Actor

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:

import asyncio
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer

from apify import Actor

processed_items = 0
http_server = None


class RequestHandler(BaseHTTPRequestHandler):
"""A handler that prints the number of processed items on every GET request."""

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

Conclusion

In this guide, you learned how to run a web server inside your Apify Actor. By leveraging the container URL and port provided by the platform, you can expose HTTP endpoints for monitoring, reporting, or serving content during Actor execution. If you have questions or need assistance, feel free to reach out on our GitHub or join our Discord community.

Additional resources