Browser automation that feels like magic β¨
Houdin is a powerful browser extension that enables visual workflow automation for web browsers. Create sophisticated automation workflows using a drag-and-drop interface, inject custom code, and automate repetitive tasks across any website.
demo-dark.mp4
Manage your automation workflows with an intuitive interface
Drag-and-drop workflow designer with extensive action library
Configure action parameters with type-safe property editors
Monitor workflow execution with detailed logs and outputs
Workflows execute seamlessly on any website
- Visual Workflow Designer: Drag-and-drop interface for creating complex automation workflows
- Element Interaction: Click, type, and interact with web page elements
- Smart Element Selection: Built-in element selector with CSS/XPath support
- Form Automation: Automated form filling and submission
- HTTP Requests: Make API calls and handle responses within workflows
- Custom Scripts: Execute JavaScript code with full page context
- LLM Integration: OpenAI integration for AI-powered automation
- Modal & Notifications: Display custom UI components on web pages
- Style Injection: Dynamically modify page appearance
- Wait Conditions: Smart waiting for page changes and elements
- TypeScript: Full type safety and IntelliSense support
- React + Mantine: Modern UI components and design system
- Hot Reload: Fast development with Vite
- Cross-Browser: Works on Chrome, Firefox, and Edge
- Execution History: Track and debug workflow runs
-
Clone the repository
git clone <repository-url> cd houdin
-
Install dependencies
npm install
-
Start development server
npm run dev
-
Load extension in browser
- Chrome: Go to
chrome://extensions/, enable Developer mode, click "Load unpacked" - Firefox: Go to
about:debugging, click "This Firefox", click "Load Temporary Add-on"
- Chrome: Go to
npm run buildThe built extension will be in the dist/ directory.
Every node (action or trigger) follows a split pattern: a definition file (metadata, config schema, output shape) and a runtime file (execution logic).
Define the node's metadata, configuration schema, and example output.
src/services/actions/my-action.definition.ts (or src/services/triggers/my-trigger.definition.ts):
import type { NodeDefinition } from "../node-definitions/types";
import { textProperty, selectProperty } from "@/types/config-properties";
const definition = {
kind: "action",
metadata: {
type: "my-action",
label: "My Action",
icon: "β‘",
description: "Description of what this action does",
disableTimeout: true, // optional: disables timeout for long-running actions
outputs: new Set(["true", "false"]), // optional: for branching nodes like "if"
},
configSchema: {
properties: {
myField: textProperty({
label: "My Field",
placeholder: "Enter value",
description: "What this field does",
required: true,
defaultValue: "hello",
}),
myChoice: selectProperty({
label: "My Choice",
options: [
{ label: "Option A", value: "a" },
{ label: "Option B", value: "b" },
],
defaultValue: "a",
}),
},
},
outputExample: {
result: "Sample output data",
},
} satisfies NodeDefinition;
export default definition;Available property builders (from @/types/config-properties):
| Function | Type |
|---|---|
textProperty() |
Single-line text |
textareaProperty() |
Multi-line text |
numberProperty() |
Numeric input |
selectProperty() |
Dropdown with options |
booleanProperty() |
Toggle/checkbox |
colorProperty() |
Color picker |
codeProperty() |
Code editor (with language and height) |
credentialsProperty() |
Credential selector (with credentialType) |
customProperty() |
Custom React component (with component) |
All properties support showWhen for conditional visibility.
Implement the execution logic by extending BaseAction or BaseTrigger.
src/services/actions/my-action.runtime.ts:
import definition from "./my-action.definition";
import { BaseAction } from "@/types/actions";
interface MyActionConfig {
myField: string;
myChoice: string;
}
interface MyActionOutput {
result: string;
}
export class MyAction extends BaseAction<MyActionConfig, MyActionOutput> {
constructor() {
super(definition);
}
async execute(
config: MyActionConfig,
workflowId: string,
nodeId: string,
onSuccess: (data?: MyActionOutput) => void,
onError: (error: Error) => void,
): Promise<void> {
try {
const result = `You chose: ${config.myChoice}`;
onSuccess({ result });
} catch (err) {
onError(err as Error);
}
}
}For triggers, extend BaseTrigger and implement the setup method instead:
import definition from "./my-trigger.definition";
import { BaseTrigger } from "@/types/triggers";
export class MyTrigger extends BaseTrigger<MyTriggerConfig, MyTriggerOutput> {
constructor() {
super(definition);
}
async setup(
config: MyTriggerConfig,
workflowId: string,
nodeId: string,
onTrigger: (data: MyTriggerOutput) => Promise<void>,
): Promise<void> {
// Set up event listeners, observers, etc.
// Call onTrigger(data) when the event occurs
}
}Add the import and registration to the appropriate initializer.
src/services/actionInitializer.ts (or src/services/triggerInitializer.ts):
import { MyAction } from "./actions/my-action.runtime";
// ...
registry.register(MyAction);Import the definition in the catalog index.
src/services/node-definitions/actions.ts (or src/services/node-definitions/triggers.ts):
import my_action from "../actions/my-action.definition";
// ...
export const actions: NodeDefinitionRecord = {
// ...
"my-action": my_action,
};npm run dev- Start development server with hot reloadnpm run dev:firefox- Build for Firefox with watch modenpm run build- Build for production (TypeScript + Vite)npm run build:firefox- Build for Firefoxnpm run type-check- Run TypeScript type checkingnpm run preview- Preview production build locallynpm run generate-definitions- Generatedist/node-definitions.jsonfrom all defintion files
src/
βββ background/ # Service worker and background scripts
βββ content/ # Content scripts injected into web pages
βββ popup/ # Extension popup interface
βββ config/ # Configuration pages and workflow designer
βββ components/ # Reusable React components
βββ services/ # Core automation services
β βββ actions/ # Workflow action implementations
β βββ triggers/ # Workflow trigger implementations
β βββ credentials/ # Credential management
βββ types/ # TypeScript type definitions
βββ utils/ # Utility functions and helpers
Houdin supports secure credential storage for:
- HTTP Authentication: Store API keys and authentication tokens
- OpenAI Integration: Securely store OpenAI API keys
- Custom Secrets: Store any sensitive configuration data
All credentials are encrypted and stored locally in the browser's extension storage.
This project is licensed under the Functional Source License 1.1 (FSL-1.1-ALv2).
- β Internal use: Use within your organization
- β Non-commercial: Education, research, and personal projects
- β Professional services: Provide services using the software
- β Modify and share: You can make changes and derivatives (must include license)
- β No competing use: Cannot create competing SaaS or similar services
- π Future open source: Automatically becomes Apache 2.0 after 2 years
β οΈ No warranty: Software provided "as is" with no guarantees
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Workflow Designer: Visual interface for creating automation workflows
- Action Registry: Extensible system for adding new automation actions
- Trigger System: Event-driven workflow execution
- Credential Management: Secure storage for API keys and secrets
- Element Selection: Advanced CSS/XPath selector tools
If you encounter any issues or have questions:
- Check existing issues in the repository
- Create a new issue with detailed reproduction steps
- Include browser version and extension logs if applicable
Version: 3.3.0 Browser Compatibility: Chrome, Firefox, Edge (Manifest V3)