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
containerUrlproperty of the Run object. - In the Actor as the
Actor.config.container_urlproperty.
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.