{"id":19482383,"url":"https://github.com/aykhans/dodo","last_synced_at":"2025-08-23T01:11:04.152Z","repository":{"id":241437876,"uuid":"805841419","full_name":"aykhans/dodo","owner":"aykhans","description":"Fast, easy-to-use HTTP benchmarking tool","archived":false,"fork":false,"pushed_at":"2025-04-18T16:41:34.000Z","size":673,"stargazers_count":3,"open_issues_count":3,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-19T00:53:49.812Z","etag":null,"topics":["cli","go","http-benchmarking"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/aykhans.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-05-25T16:02:42.000Z","updated_at":"2025-04-18T11:42:25.000Z","dependencies_parsed_at":"2024-08-07T13:29:46.483Z","dependency_job_id":"acb8439d-ab75-4fb0-a2b4-428592446a96","html_url":"https://github.com/aykhans/dodo","commit_stats":null,"previous_names":["aykhans/dodo"],"tags_count":21,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aykhans%2Fdodo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aykhans%2Fdodo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aykhans%2Fdodo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aykhans%2Fdodo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aykhans","download_url":"https://codeload.github.com/aykhans/dodo/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250844493,"owners_count":21496590,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","go","http-benchmarking"],"created_at":"2024-11-10T20:09:56.669Z","updated_at":"2025-08-23T01:11:04.135Z","avatar_url":"https://github.com/aykhans.png","language":"Go","readme":"\u003ch1 align=\"center\"\u003eDodo - A Fast and Easy-to-Use HTTP Benchmarking Tool\u003c/h1\u003e\n\n![Usage](https://ftp.aykhans.me/web/client/pubshares/VzPtSHS7yPQT7ngoZzZSNU/browse?path=/dodo_demonstrate.gif)\n\n\u003cdiv align=\"center\"\u003e\n  \u003ch4\u003e\n      \u003ca href=\"./EXAMPLES.md\"\u003e\n          Examples\n      \u003c/a\u003e\n      \u003cspan\u003e | \u003c/span\u003e\n      \u003ca href=\"#installation\"\u003e\n          Install\n      \u003c/a\u003e\n      \u003cspan\u003e | \u003c/span\u003e\n      \u003ca href=\"https://hub.docker.com/r/aykhans/dodo\"\u003e\n          Docker\n      \u003c/a\u003e\n  \u003c/h4\u003e\n  \u003cbr\u003e\n    \u003ca href=\"https://coff.ee/aykhan\"\u003e\n        \u003cimg src=\"https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png\" alt=\"Buy Me A Coffee\" style=\"height: 40px !important;width: 150px !important;\"\u003e\n    \u003c/a\u003e\n\u003c/div\u003e\n\n## Table of Contents\n\n- [Installation](#installation)\n    - [Using Docker (Recommended)](#using-docker-recommended)\n    - [Using Pre-built Binaries](#using-pre-built-binaries)\n    - [Building from Source](#building-from-source)\n- [Usage](#usage)\n    - [1. CLI Usage](#1-cli-usage)\n    - [2. Config File Usage](#2-config-file-usage)\n        - [2.1 YAML/YML Example](#21-yamlyml-example)\n        - [2.2 JSON Example](#22-json-example)\n    - [3. CLI \u0026 Config File Combination](#3-cli--config-file-combination)\n- [Config Parameters Reference](#config-parameters-reference)\n- [Template Functions](#template-functions)\n\n## Installation\n\n### Using Docker (Recommended)\n\nPull the latest Dodo image from Docker Hub:\n\n```sh\ndocker pull aykhans/dodo:latest\n```\n\nTo use Dodo with Docker and a local config file, mount the config file as a volume and pass it as an argument:\n\n```sh\ndocker run -v /path/to/config.json:/config.json aykhans/dodo -f /config.json\n```\n\nIf you're using a remote config file via URL, you don't need to mount a volume:\n\n```sh\ndocker run aykhans/dodo -f https://raw.githubusercontent.com/aykhans/dodo/main/config.yaml\n```\n\n### Using Pre-built Binaries\n\nDownload the latest binaries from the [releases](https://github.com/aykhans/dodo/releases) section.\n\n### Building from Source\n\nTo build Dodo from source, ensure you have [Go 1.24+](https://golang.org/dl/) installed.\n\n```sh\ngo install -ldflags \"-s -w\" github.com/aykhans/dodo@latest\n```\n\n## Usage\n\nDodo supports CLI arguments, configuration files (JSON/YAML), or a combination of both. If both are used, CLI arguments take precedence.\n\n### 1. CLI Usage\n\nSend 1000 GET requests to https://example.com with 10 parallel dodos (threads), each with a timeout of 2 seconds, within a maximum duration of 1 minute:\n\n```sh\ndodo -u https://example.com -m GET -d 10 -r 1000 -o 1m -t 2s\n```\n\nWith Docker:\n\n```sh\ndocker run --rm -i aykhans/dodo -u https://example.com -m GET -d 10 -r 1000 -o 1m -t 2s\n```\n\n### 2. Config File Usage\n\nSend 1000 GET requests to https://example.com with 10 parallel dodos (threads), each with a timeout of 800 milliseconds, within a maximum duration of 250 seconds:\n\n#### 2.1 YAML/YML Example\n\n```yaml\nmethod: \"GET\"\nurl: \"https://example.com\"\nyes: false\ntimeout: \"800ms\"\ndodos: 10\nrequests: 1000\nduration: \"250s\"\nskip_verify: false\n\nparams:\n    # A random value will be selected from the list for first \"key1\" param on each request\n    # And always \"value\" for second \"key1\" param on each request\n    # e.g. \"?key1=value2\u0026key1=value\"\n    - key1: [\"value1\", \"value2\", \"value3\", \"value4\"]\n    - key1: \"value\"\n\n    # A random value will be selected from the list for param \"key2\" on each request\n    # e.g. \"?key2=value2\"\n    - key2: [\"value1\", \"value2\"]\n\nheaders:\n    # A random value will be selected from the list for first \"key1\" header on each request\n    # And always \"value\" for second \"key1\" header on each request\n    # e.g. \"key1: value3\", \"key1: value\"\n    - key1: [\"value1\", \"value2\", \"value3\", \"value4\"]\n    - key1: \"value\"\n\n    # A random value will be selected from the list for header \"key2\" on each request\n    # e.g. \"key2: value2\"\n    - key2: [\"value1\", \"value2\"]\n\ncookies:\n    # A random value will be selected from the list for first \"key1\" cookie on each request\n    # And always \"value\" for second \"key1\" cookie on each request\n    # e.g. \"key1=value4; key1=value\"\n    - key1: [\"value1\", \"value2\", \"value3\", \"value4\"]\n    - key1: \"value\"\n\n    # A random value will be selected from the list for cookie \"key2\" on each request\n    # e.g. \"key2=value1\"\n    - key2: [\"value1\", \"value2\"]\n\nbody: \"body-text\"\n# OR\n# A random body value will be selected from the list for each request\nbody:\n    - \"body-text1\"\n    - \"body-text2\"\n    - \"body-text3\"\n\nproxy: \"http://example.com:8080\"\n# OR\n# A random proxy will be selected from the list for each request\nproxy:\n    - \"http://example.com:8080\"\n    - \"http://username:password@example.com:8080\"\n    - \"socks5://example.com:8080\"\n    - \"socks5h://example.com:8080\"\n```\n\n```sh\ndodo -f /path/config.yaml\n# OR\ndodo -f https://example.com/config.yaml\n```\n\nWith Docker:\n\n```sh\ndocker run --rm -i -v /path/to/config.yaml:/config.yaml aykhans/dodo -f /config.yaml\n# OR\ndocker run --rm -i aykhans/dodo -f https://example.com/config.yaml\n```\n\n#### 2.2 JSON Example\n\n```jsonc\n{\n    \"method\": \"GET\",\n    \"url\": \"https://example.com\",\n    \"yes\": false,\n    \"timeout\": \"800ms\",\n    \"dodos\": 10,\n    \"requests\": 1000,\n    \"duration\": \"250s\",\n    \"skip_verify\": false,\n\n    \"params\": [\n        // A random value will be selected from the list for first \"key1\" param on each request\n        // And always \"value\" for second \"key1\" param on each request\n        // e.g. \"?key1=value2\u0026key1=value\"\n        { \"key1\": [\"value1\", \"value2\", \"value3\", \"value4\"] },\n        { \"key1\": \"value\" },\n\n        // A random value will be selected from the list for param \"key2\" on each request\n        // e.g. \"?key2=value2\"\n        { \"key2\": [\"value1\", \"value2\"] },\n    ],\n\n    \"headers\": [\n        // A random value will be selected from the list for first \"key1\" header on each request\n        // And always \"value\" for second \"key1\" header on each request\n        // e.g. \"key1: value3\", \"key1: value\"\n        { \"key1\": [\"value1\", \"value2\", \"value3\", \"value4\"] },\n        { \"key1\": \"value\" },\n\n        // A random value will be selected from the list for header \"key2\" on each request\n        // e.g. \"key2: value2\"\n        { \"key2\": [\"value1\", \"value2\"] },\n    ],\n\n    \"cookies\": [\n        // A random value will be selected from the list for first \"key1\" cookie on each request\n        // And always \"value\" for second \"key1\" cookie on each request\n        // e.g. \"key1=value4; key1=value\"\n        { \"key1\": [\"value1\", \"value2\", \"value3\", \"value4\"] },\n        { \"key1\": \"value\" },\n\n        // A random value will be selected from the list for cookie \"key2\" on each request\n        // e.g. \"key2=value1\"\n        { \"key2\": [\"value1\", \"value2\"] },\n    ],\n\n    \"body\": \"body-text\",\n    // OR\n    // A random body value will be selected from the list for each request\n    \"body\": [\"body-text1\", \"body-text2\", \"body-text3\"],\n\n    \"proxy\": \"http://example.com:8080\",\n    // OR\n    // A random proxy will be selected from the list for each request\n    \"proxy\": [\n        \"http://example.com:8080\",\n        \"http://username:password@example.com:8080\",\n        \"socks5://example.com:8080\",\n        \"socks5h://example.com:8080\",\n    ],\n}\n```\n\n```sh\ndodo -f /path/config.json\n# OR\ndodo -f https://example.com/config.json\n```\n\nWith Docker:\n\n```sh\ndocker run --rm -i -v /path/to/config.json:/config.json aykhans/dodo\n# OR\ndocker run --rm -i aykhans/dodo -f https://example.com/config.json\n```\n\n### 3. CLI \u0026 Config File Combination\n\nCLI arguments override config file values:\n\n```sh\ndodo -f /path/to/config.yaml -u https://example.com -m GET -d 10 -r 1000 -o 1m -t 5s\n```\n\nWith Docker:\n\n```sh\ndocker run --rm -i -v /path/to/config.json:/config.json aykhans/dodo -f /config.json -u https://example.com -m GET -d 10 -r 1000 -o 1m -t 5s\n```\n\nYou can find more usage examples in the [EXAMPLES.md](./EXAMPLES.md) file.\n\n## Config Parameters Reference\n\nIf `Headers`, `Params`, `Cookies`, `Body`, or `Proxy` fields have multiple values, each request will choose a random value from the list.\n\n| Parameter       | config file | CLI Flag     | CLI Short Flag | Type                           | Description                                                 | Default |\n| --------------- | ----------- | ------------ | -------------- | ------------------------------ | ----------------------------------------------------------- | ------- |\n| Config file     |             | -config-file | -f             | String                         | Path to local config file or http(s) URL of the config file | -       |\n| Yes             | yes         | -yes         | -y             | Boolean                        | Answer yes to all questions                                 | false   |\n| URL             | url         | -url         | -u             | String                         | URL to send the request to                                  | -       |\n| Method          | method      | -method      | -m             | String                         | HTTP method                                                 | GET     |\n| Dodos (Threads) | dodos       | -dodos       | -d             | UnsignedInteger                | Number of dodos (threads) to send requests in parallel      | 1       |\n| Requests        | requests    | -requests    | -r             | UnsignedInteger                | Total number of requests to send                            | -       |\n| Duration        | duration    | -duration    | -o             | Time                           | Maximum duration for the test                               | -       |\n| Timeout         | timeout     | -timeout     | -t             | Time                           | Timeout for canceling each request                          | 10s     |\n| Params          | params      | -param       | -p             | [{String: String OR [String]}] | Request parameters                                          | -       |\n| Headers         | headers     | -header      | -H             | [{String: String OR [String]}] | Request headers                                             | -       |\n| Cookies         | cookies     | -cookie      | -c             | [{String: String OR [String]}] | Request cookies                                             | -       |\n| Body            | body        | -body        | -b             | String OR [String]             | Request body or list of request bodies                      | -       |\n| Proxy           | proxies     | -proxy       | -x             | String OR [String]             | Proxy URL or list of proxy URLs                             | -       |\n| Skip Verify     | skip_verify | -skip-verify |                | Boolean                        | Skip SSL/TLS certificate verification                       | false   |\n\n## Template Functions\n\nDodo supports template functions in `Headers`, `Params`, `Cookies`, and `Body` fields. These functions allow you to generate dynamic values for each request.\n\nYou can use Go template syntax to include dynamic values in your requests. Here's how to use template functions:\n\nIn CLI config:\n\n```sh\ndodo -u https://example.com -r 1 \\\n    -header \"User-Agent:{{ fakeit_UserAgent }}\" \\ # e.g. \"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)\"\n    -param \"username={{ strings_ToUpper fakeit_Username }}\" \\ # e.g. \"username=JOHN BOB\"\n    -cookie \"token={{ fakeit_Password true true true true true 10 }}\" \\ # e.g. token=1234567890abcdef1234567890abcdef\n    -body '{\"email\":\"{{ fakeit_Email }}\", \"password\":\"{{ fakeit_Password true true true true true 10 }}\"}' # e.g. {\"email\":\"john.doe@example.com\", \"password\":\"12rw4d-78d\"}\n```\n\nIn YAML/YML config:\n\n```yaml\nheaders:\n    - User-Agent: \"{{ fakeit_UserAgent }}\" # e.g. \"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)\"\n    - \"Random-Header-{{fakeit_FirstName}}\": \"static_value\" # e.g. \"Random-Header-John: static_value\"\n\ncookies:\n    - token: \"Bearer {{ fakeit_UUID }}\" # e.g. \"token=Bearer 1234567890abcdef1234567890abcdef\"\n\nparams:\n    - id: \"{{ fakeit_Uint }}\" # e.g. \"id=1234567890\"\n    - username: \"{{ fakeit_Username }}\" # e.g. \"username=John Doe\"\n\nbody:\n    - '{ \"username\": \"{{ fakeit_Username }}\", \"password\": \"{{ fakeit_Password }}\" }' # e.g. { \"username\": \"john.doe\", \"password\": \"password123\" }\n    - '{ \"email\": \"{{ fakeit_Email }}\", \"phone\": \"{{ fakeit_Phone }}\" }' # e.g. { \"email\": \"john.doe@example.com\", \"phone\": \"1234567890\" }\n    - '{{ body_FormData (dict_Str \"username\" fakeit_Username \"password\" \"secret123\") }}' # Creates multipart form data for form submissions, automatically sets the appropriate Content-Type header.\n```\n\nIn JSON config:\n\n```jsonc\n{\n    \"headers\": [\n        { \"User-Agent\": \"{{ fakeit_UserAgent }}\" }, // e.g. \"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)\"\n    ],\n    \"body\": [\n        \"{ \\\"username\\\": \\\"{{ strings_RemoveSpaces fakeit_Username }}\\\", \\\"password\\\": \\\"{{ fakeit_Password }}\\\" }\", // e.g. { \"username\": \"johndoe\", \"password\": \"password123\" }\n        \"{{ body_FormData (dict_Str \\\"username\\\" fakeit_Username \\\"password\\\" \\\"12345\\\") }}\", // Creates multipart form data for form submissions, automatically sets the appropriate Content-Type header.\n    ],\n}\n```\n\nFor the full list of template functions over 200 functions, refer to the `NewFuncMap` function in `utils/templates.go`.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faykhans%2Fdodo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faykhans%2Fdodo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faykhans%2Fdodo/lists"}