¿Alguna vez te has preguntado qué pasaría si en lugar de limitarte a crear un bot que navega páginas y hace clics, pudieras transformarlo en un servicio que cualquiera puede consumir desde la web? 🤔
En el mundo de la automatización, muchas veces empezamos creando un bot sencillo en Python para hacer clics, leer precios o extraer datos de una página. 🚀
Pero ¿qué pasa cuando queremos que ese bot no viva solo en nuestro computador, sino que cualquiera pueda consumirlo como un servicio REST desde otra aplicación?
En este artículo te muestro cómo lo hice paso a paso, para este proyecto utilicé Python, Selenium y FastAPI porque son herramientas sencillas de implementar y ayudan a explicar de manera clara la idea de transformar un bot en un servicio REST capaz de devolver datos en formato JSON, listo para integrarse en cualquier aplicación 🚀. Además, te comparto el código en GitHub y ejemplos en vivo para que puedas probarlos.
Sin embargo, no son las únicas alternativas: existen muchas otras como Playwright, Puppeteer, Scrapy u otros frameworks para exponer APIs. Cada una tiene sus ventajas y se adapta mejor a distintos escenarios o preferencias.
Lo valioso aquí es entender el funcionamiento: cómo un bot puede automatizar tareas repetitivas y luego convertirse en un servicio que entrega datos en formato JSON. Una vez comprendido, ya puedes apoyarte en la IA para construir soluciones más avanzadas, eligiendo las herramientas que mejor se ajusten a tus necesidades.

🌍 ¿Por qué crear bots web?
Porque un bot aislado solo sirve en tu máquina. Pero al exponerlo como servicio:
- 🔄 Puedes reutilizarlo en distintas aplicaciones.
- 📱 Lo consumes desde tu web, móvil o cualquier cliente.
- 🤝 Lo compartes con otros equipos sin darles acceso al código.
- ⚡ Escalas fácilmente con infraestructura en la nube.
🧩 Parte 1 – Construyendo el bot con Selenium y Python
Para este ejemplo, usé Selenium en Python. La idea era simular la navegación en una tienda online, capturar productos y precios y devolver esa información.
Lo más importante es la organización del proyecto y tratar un código lo más limpio posible y fácil de mantener, en este caso implementamos el patrón Page Object Model (POM), que separa los elementos, las acciones y la ejecución en diferentes archivos:
- Archivo de elementos → guarda todos los selectores de la página. page_katro.py → donde defino los elementos de la página (selectores XPATH).
- Archivo de acciones → define qué hace el bot con esos elementos. actions.py → donde centralizo todas las acciones repetitivas (clics, scroll, obtener texto, etc.).
- Archivo ejecutor → orquesta todo y devuelve el resultado. appExecution.py → donde orquesto el bot usando los elementos y acciones.
📌 Nota: Los siguientes archivos son fragmentos de un bot de ejemplo, diseñados únicamente para mostrar cómo organizar un proyecto con POM. No es el bot completo, pero sí una pequeña guía clara de cómo separar elementos, acciones y ejecución.
page_katro.py – Definición de elementos de la página Ktronix
from selenium.webdriver.common.by import By
class KatroHome:
cel = (By.XPATH,"(//a[@title='Celulares'])[1]")
celu = (By.XPATH,"//a[@data-subcategory='Celulares']")
notifi = (By.XPATH,"//button[@class='button-primary js-cookie-notification-accept']")
class KatroCell:
order = (By.XPATH,"//div[@class='float-select js-float-select js-float-group full-width active-click']")
menor = (By.XPATH,"//li[contains(.,'Precio: menor a mayor')]")
@staticmethod
def val_element(val):
return (By.XPATH, f"(//span[contains(@class,'price')])[{val}]")
actions.py – Métodos reutilizables para acciones sobre la página
import time
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys
class Actions:
@staticmethod
def open_url(driver, url):
driver.get(url)
@staticmethod
def move_to_element(driver, selector):
acciones = ActionChains(driver)
elementMove = driver.find_element(*selector)
acciones.move_to_element(elementMove).perform()
appExecution.py – Script principal que integra páginas y acciones
from selenium import webdriver
from selenium.webdriver.support import expected_conditions as EC
from unidecode import unidecode
from page_katro import *
from actions import *
def createDriver() -> webdriver.Chrome:
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument("--headless")
chrome_options.add_argument("--no-sandbox")
chrome_options.add_argument("--disable-dev-shm-usage")
chrome_options.add_argument("user-agent=Chrome/100.0.1000.0")
prefs = {"profile.managed_default_content_settings.images":2}
chrome_options.headless = True
chrome_options.add_experimental_option("prefs", prefs)
myDriver = webdriver.Chrome(options=chrome_options)
# Alternativa con webdriver_manager si no tienes chromedriver instalado:
# from webdriver_manager.chrome import ChromeDriverManager
# from selenium.webdriver.chrome.service import Service
#myDriver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=chrome_options)
return myDriver
def getBotSearchOffer(driver: webdriver.Chrome) -> str:
Actions.set_window_position(driver, 0, 0)
Actions.set_window_size(driver, 1496, 1024)
data ={}
referencia = []
valor =[]
Actions.open_url(driver, "https://www.ktronix.com/")
Actions.wait(5)
Actions.move_to_element(driver, KatroHome.cel)
Actions.wait(5)
Actions.click_element(driver, KatroHome.celu)
Actions.wait(3)
Actions.if_click_element(driver, KatroHome.notifi)
Actions.scroll_to(driver,751,631)
Actions.wait(3)
Actions.click_element(driver, KatroCell.order)
Actions.click_element(driver, KatroCell.menor)
Actions.wait(5)
valPrice=1
for i in range(3) :
valRef=str(i+1)
ref = Actions.get_text(driver, KatroCell.ref_element(valRef))
val = Actions.get_text(driver, KatroCell.val_element(str(valPrice)))
referencia.append(ref)
valor.append(val)
valPrice+=2
data['Ktronix']=[referencia, valor]
return(data)
🧩 Parte 2 – Llevando el bot a un servicio REST con FastAPI
En este archivo convertimos nuestro bot en un servicio accesible mediante FastAPI.
Aquí se definen las rutas, la configuración de CORS, la carga de la página principal y un endpoint que ejecuta el bot y devuelve resultados en formato JSON.
appExecution.py – Script principal que integra páginas y acciones
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from appExecution import *
from fastapi.responses import HTMLResponse, JSONResponse
app = FastAPI()
# Orígenes permitidos (ajusta según tu dominio)
origins = [
"https://tu-dominio.com" # Cambia este dominio por el tuyo
]
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # Si quieres restringir, reemplaza con: origins
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
class Msg(BaseModel):
msg: str
secret: str
@app.get("/")
async def root():
with open("index.html", "r") as file:
html_content = file.read()
return HTMLResponse(content=html_content, status_code=200)
@app.get("/botSearchOffer")
async def demo_get():
driver = createDriver()
listOffers = getBotSearchOffer(driver)
driver.quit()
return JSONResponse(content={"listOffer": listOffers})
Ahora, al llamar la URL del endpoint, el bot se ejecuta en segundo plano, navega por la web y devuelve un JSON con los resultados.
🧩 Parte 3 – Desplegando en Railway – Llevando el bot a producción
En lugar de dejarlo en local, opté por Railway, una plataforma muy práctica y sencilla para proyectos pequeños con Python + FastAPI, lo que permite:
- Exponerlo públicamente.
- Integrarlo en un portafolio web.
- Tener endpoints listos para consumir desde cualquier app o frontend.
No es la única herramienta de despliegue (existen alternativas como Render, Heroku, Vercel o incluso servidores propios), pero, en mi consideración, Railway ofrece un flujo muy directo y rápido, ideal para este tipo de proyectos personales o demostrativos.
Con este paso, mi bot pasó de ser un simple script local que solo corría en mi máquina, a convertirse en un servicio REST accesible desde cualquier lugar, listo para integrarse con aplicaciones externas o probarse desde herramientas como Postman o el navegador.
Ejemplo de Salida en JSON
{"listOffer":
"Ktronix":
[
["KALLEY"],
["KALLEY"],
["ZTE"]
],
[
["$239.900"],
["$239.900"],
["$269.900"]
]
}
📊 Ejemplo de resultados
Imagina que buscas celulares ordenados por precio de menor a mayor. El bot podría devolver algo como esto.

💡 La IA impulsa, el entendimiento sostiene
Claro que puedes pedirle a la IA que genere un bot por ti (yo misma lo hago muchas veces 😅). Pero entender cómo funciona un bot, cómo organizarlo y cómo exponerlo como servicio REST te da un súper poder extra:
- Te permite personalizar y adaptar el bot a cualquier necesidad.
- Te da la capacidad de mantener y escalar tu solución.
- Abrir la puerta a proyectos más grandes (integraciones, análisis de datos, automatización de procesos).
- Y lo más importante: entiendes lo que pasa detrás del “código mágico” que genera la IA.
👉 Y lo mejor es que tú también puedes hacerlo. La próxima vez que pienses en pedirle a la IA que “te haga un bot”, recuerda que entender la lógica detrás es lo que realmente te da poder para construir soluciones increíbles.