The URI module in Ansible is your bridge to interact with web services and REST APIs directly from your playbooks. It also supports HTTP and HTTPs protocols that enables you to send GET, POST, PUT, DELETE, and other similar requests. This module is mainly useful for tasks such as triggering webhooks, querying cloud services, or automating interactions with third-party APIs.
In this guide, we will learn all about the Ansible URI module to work with infrastructure-as-a-code, CI/CD systems, or cloud platforms.
Setting Up: Requirements and Environment
Before you start working with any new module, you need to ensure that your system is updated with the right project environment configurations. Here are the prerequisites that you need to follow for perfect execution of Ansible URI module.
System Requirements
Requirement | Description |
Ansible Version | Ansible 2.0+ supports the uri module, but it’s recommended to use Ansible 2.9 or later for better stability and newer features. |
Python | Ansible requires Python on the control node (Python 3.6+ is ideal). It uses Python’s urllib module to handle HTTP requests. |
Operating System | Compatible with Linux/macOS control nodes. Windows Subsystem for Linux (WSL) can also be used. |
Networking and Connectivity
- You need to have outbound access to the URL that you intend to call.
- If you are using the module to interact with the internal APIs, make sure that you can control the nodes that reach those hosts over the network.
- Firewalls and proxies must allow HTTP/ HTTPs traffic to target the endpoint.
Installing Ansible
- If Ansible isn’t installed yet, here’s a quick way to get started on most Linux systems:
sudo apt update
sudo apt install ansible
- Or install the latest version using pip:
pip install ansible
Get exclusive access to all things tech-savvy, and be the first to receive
the latest updates directly in your inbox.
- Verify installation:
ansible –version
Creating a Test Environment
Test the Ansible URI module functionality by:
- Use a mock API service like https://httpbin.org or https://reqres.in
- Set up a local REST API server using tools like Flask, FastAPI, or json-server
- Test against real APIs only if you have permission and valid credentials
Sample Inventory and Playbook Setup
You can run URI based tasks on localhost without remote hosts access. Here is a minimal inventory setup.
[local]
localhost ansible_connection=local
And your playbook should target the localhost group:
– name: Example playbook
hosts: localhost
connection: local
tasks:

– name: Sample API call
ansible.builtin.uri:
url: https://httpbin.org/get
method: GET
return_content: yes
By making sure that your system follows these, you can run Ansible URI modules without any bottlenecks.
Understanding URI Module Syntax and Parameters
The uri module syntax fits within a standard Ansible task. Here’s a basic example of the structure:
– name: Make a GET request
ansible.builtin.uri:
url: https://api.example.com/data
method: GET
return_content: yes
status_code: 200
register: api_response
Common Parameters:
- url — The target URL of the HTTP request (required)
- method — HTTP method to use (GET, POST, PUT, DELETE, etc.)
- headers — Dictionary of custom headers (e.g., for auth or content-type)
- body — Payload to send in the request (used with POST/PUT)
- body_format — Format of the body (json, raw, etc.)
- status_code — Expected HTTP status code(s) to validate success
- return_content — If set to yes, returns response body in content
Making Your First API Call with the URI Module
Let’s look at a simple example to fetch data from an API using a GET request:
– name: Fetch public IP address using httpbin
hosts: localhost
tasks:
– name: Get IP address
ansible.builtin.uri:
url: https://httpbin.org/ip
method: GET
return_content: yes
status_code: 200
register: result
– name: Show API response
debug:
var: result.content
What This Does:
- Sends a GET request to https://httpbin.org/ip
- Validates that the HTTP response code is 200
- Saves the response in the result variable
- Outputs the content (your public IP address)
Sending Data: POST and PUT Requests
The URI module allows you to send data with different methods like POST, PUT, and PATCH. These are typically used to create or update resources on an API server.
Example: POST Request with JSON Payload
– name: Create a user via POST request
ansible.builtin.uri:
url: https://reqres.in/api/users
method: POST
headers:
Content-Type: “application/json”
body: |
{
“name”: “John Doe”,
“job”: “Developer”
}
body_format: json
return_content: yes
status_code: 201
register: post_response
– name: Display POST response
debug:
var: post_response.content
Explanation:
- method: POST specifies the request type.
- headers defines the Content-Type as application/json.
- body contains the data to send.
- body_format: json tells Ansible to treat the body as JSON.
- status_code: 201 expects a “Created” response.
Example: PUT Request to Update a Record
– name: Update user via PUT request
ansible.builtin.uri:
url: https://reqres.in/api/users/2
method: PUT
headers:
Content-Type: “application/json”
body: |
{
“name”: “Jane Doe”,
“job”: “Senior Developer”
}
body_format: json
status_code: 200
register: put_response
Use PUT when you want to replace or update a resource.
Managing Authentication and Headers
Many APIs require you to authenticate and customize headers. The URI module helps you by supporting multiple methods including Basic Auth, Bearer Tokens, and custom headers.
Basic Authentication Example
– name: Basic Auth Example
ansible.builtin.uri:
url: https://example.com/api/data
method: GET
user: myuser
password: mypass
force_basic_auth: yes
return_content: yes
- user and password: Your API credentials.
- force_basic_auth: Ensures credentials are sent even if the server doesn’t challenge.
Bearer Token (OAuth) Example
– name: Bearer Token Auth
ansible.builtin.uri:
url: https://api.example.com/protected
method: GET
headers:
Authorization: “Bearer YOUR_API_TOKEN”
return_content: yes
Custom Headers
You can include any custom headers required by your API:
headers:
X-Custom-Header: “CustomValue”
Content-Type: “application/json”
Use headers to pass tokens, content types, API keys, and more.
Error Handling and Status Code Validation
Proper error handling is essential for making your playbooks reliable while using the Ansible URI module.
- Checking for Expected HTTP Status Codes
Use the status_code command to make sure that you receive the right HTTP response.
– name: Expect 200 OK
ansible.builtin.uri:
url: https://httpbin.org/status/200
method: GET
status_code: 200
You can also specify multiple accepted codes:
status_code:
– 200
– 204
- Handling Failed Requests Gracefully
Use the failed_when clause to control task failure:
– name: Fail if response not 201
ansible.builtin.uri:
url: https://example.com/create
method: POST
status_code: 201
register: response
failed_when: response.status != 201
- Debugging and Logging Responses
Make sure that you always store the output in an Ansible register and use debug to see what is going on.
– debug:
var: response
- Timeouts and Retries
You can set request timeouts to avoid hanging playbooks:
timeout: 10
Ansible URI Module – Troubleshooting Guide
Issue | Cause | Solution |
Invalid or unexpected HTTP status code | API returns a status code not listed in status_code | Add all valid codes using status_code: [200, 201, 202] |
SSL certificate errors | Self-signed or expired certificate | Use validate_certs: no (only in trusted environments) |
Request hangs or times out | Slow network or unreachable server | Add timeout: 10 to avoid long waits |
Authentication fails (401/403) | Missing or incorrect credentials or token | Use user, password, force_basic_auth: yes, or set proper Authorization header |
Content-type or body format error | Missing or incorrect Content-Typeheader or body_format | Set headers: Content-Type: application/jsonand use body_format: json |
No content returned in response | return_content not enabled | Add return_content: yes to capture response body |
Playbook fails with unclear message | Lack of verbose logs or missing debug output | Run with -vvv and use the debug module to inspect variables |
DNS or proxy connectivity issues | Control node cannot resolve or reach target URL | Check DNS resolution, proxy settings, or use curl to test connectivity manually |
Wrapping up
The Ansible URI module is an extremely powerful tool when used properly for integrating HTTP-based APIs into your automation workflow. By understanding and learning the right way to use it, you can build robust automations for your system!
Can I use the URI module to send data via POST or PUT?
Yes, the module supports various HTTP methods including GET
, POST
, PUT
, PATCH
, and DELETE
for sending or modifying data.
What should I do if I get SSL certificate errors?
Use validate_certs: no
to bypass SSL validation, especially when working with self-signed certificates (for non-production environments).
Is the Ansible URI module included by default?
Yes, the URI module is included in the default Ansible installation and doesn’t require any extra dependencies.