> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/grafana/k6/llms.txt
> Use this file to discover all available pages before exploring further.

# HTTP Requests

> Making HTTP requests with the k6 http module

# HTTP Requests

The `k6/http` module is the core of most k6 tests. It provides methods for making HTTP requests and handling responses.

## Basic GET Request

The simplest k6 test makes a GET request:

```javascript theme={null}
import http from 'k6/http';

export default function () {
  http.get('https://quickpizza.grafana.com');
}
```

## HTTP Methods

k6 supports all standard HTTP verbs:

<CodeGroup>
  ```javascript GET theme={null}
  import http from 'k6/http';
  import { check } from 'k6';

  export default function() {
    let res = http.get('http://httpbin.org/get?verb=get');
    check(res, {
      'status is 200': (r) => r.status === 200,
    });
  }
  ```

  ```javascript POST theme={null}
  import http from 'k6/http';

  export default function() {
    let res = http.post('http://httpbin.org/post', { 
      verb: 'post' 
    });
    check(res, {
      'status is 200': (r) => r.status === 200,
    });
  }
  ```

  ```javascript PUT theme={null}
  import http from 'k6/http';

  export default function() {
    let payload = JSON.stringify({ verb: 'put' });
    let params = {
      headers: { 'Content-Type': 'application/json' }
    };
    let res = http.put('http://httpbin.org/put', payload, params);
  }
  ```

  ```javascript DELETE theme={null}
  import http from 'k6/http';

  export default function() {
    let res = http.del('http://httpbin.org/delete?verb=delete');
    check(res, {
      'status is 200': (r) => r.status === 200,
    });
  }
  ```
</CodeGroup>

## Request Parameters

Customize requests with parameters:

```javascript theme={null}
import http from 'k6/http';

export default function() {
  let params = {
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer token123',
      'User-Agent': 'k6-test',
    },
    tags: {
      name: 'CreateOrder',
      api_version: 'v2',
    },
    timeout: '60s',
  };

  http.post('https://quickpizza.grafana.com/api/orders', 
    JSON.stringify({ items: ['pizza'] }),
    params
  );
}
```

## Handling Response Data

The response object contains all the information about the HTTP response:

```javascript theme={null}
import http from 'k6/http';
import { check } from 'k6';

export default function() {
  let res = http.get('https://quickpizza.grafana.com/api/menu');
  
  // Status code
  console.log('Status:', res.status);
  
  // Response body as string
  console.log('Body:', res.body);
  
  // Parse JSON response
  let menu = res.json();
  console.log('Items:', menu.items.length);
  
  // Access specific JSON field
  let firstItem = res.json('items.0.name');
  
  // Response headers
  console.log('Content-Type:', res.headers['Content-Type']);
  
  // Timing information
  console.log('Duration:', res.timings.duration, 'ms');
  console.log('Waiting:', res.timings.waiting, 'ms');
  console.log('Connecting:', res.timings.connecting, 'ms');
}
```

## Form Data and POST Requests

<Tabs>
  <Tab title="URL-Encoded Form">
    ```javascript theme={null}
    import http from 'k6/http';
    import { check } from 'k6';

    const form_data = {
      name: 'Test Name',
      telephone: '123456789',
      email: 'test@example.com',
      comment: 'Hello world!',
      topping: ['onion', 'bacon', 'cheese']
    };

    export default function() {
      // Passing object automatically form-urlencodes it
      let res = http.post('http://httpbin.org/post', form_data);
      
      check(res, {
        'status is 200': (r) => r.status === 200,
        'has correct name': (r) => r.json().form.name === form_data.name,
      });
    }
    ```
  </Tab>

  <Tab title="JSON Payload">
    ```javascript theme={null}
    import http from 'k6/http';

    export default function() {
      let payload = JSON.stringify({
        name: 'Test Name',
        email: 'test@example.com',
        items: ['pizza', 'soda']
      });
      
      let params = {
        headers: { 'Content-Type': 'application/json' }
      };
      
      http.post('https://quickpizza.grafana.com/api/orders', payload, params);
    }
    ```
  </Tab>

  <Tab title="Multipart Form">
    ```javascript theme={null}
    import http from 'k6/http';

    export default function() {
      let data = {
        field: 'value',
        file: http.file(open('image.png', 'b'), 'image.png'),
      };
      
      http.post('http://httpbin.org/post', data);
    }
    ```
  </Tab>
</Tabs>

## Authentication

<CodeGroup>
  ```javascript Basic Auth (URL) theme={null}
  import http from 'k6/http';
  import { check } from 'k6';

  export default function() {
    // Username and password in URL
    let res = http.get('http://user:passwd@httpbin.org/basic-auth/user/passwd');
    
    check(res, {
      'is authenticated': (r) => r.json().authenticated === true,
    });
  }
  ```

  ```javascript Basic Auth (Header) theme={null}
  import encoding from 'k6/encoding';
  import http from 'k6/http';

  export default function() {
    let credentials = encoding.b64encode('user:passwd');
    let params = {
      headers: { 'Authorization': `Basic ${credentials}` }
    };
    
    http.get('http://httpbin.org/basic-auth/user/passwd', params);
  }
  ```

  ```javascript Bearer Token theme={null}
  import http from 'k6/http';

  export function setup() {
    let loginRes = http.post('https://quickpizza.grafana.com/api/login', {
      username: 'test@example.com',
      password: 'password123'
    });
    return { token: loginRes.json('token') };
  }

  export default function(data) {
    let params = {
      headers: { 'Authorization': `Bearer ${data.token}` }
    };
    http.get('https://quickpizza.grafana.com/api/orders', params);
  }
  ```
</CodeGroup>

## Batch Requests

Make multiple requests in parallel:

```javascript theme={null}
import { check } from 'k6';
import http from 'k6/http';

export default function() {
  const responses = http.batch([
    'https://quickpizza.grafana.com/test.k6.io',
    'https://quickpizza.grafana.com/pi.php',
    ['GET', 'https://quickpizza.grafana.com/api/menu'],
    {
      method: 'POST',
      url: 'https://quickpizza.grafana.com/api/orders',
      body: JSON.stringify({ items: ['pizza'] }),
      params: { headers: { 'Content-Type': 'application/json' } },
    },
  ]);

  check(responses[0], {
    'main page 200': res => res.status === 200,
  });
  
  check(responses[1], {
    'pi page has right content': res => res.body === '3.14',
  });
}
```

<Note>
  Batch requests are executed in parallel from the VU's perspective, but they still count as separate requests in your metrics.
</Note>

## Cookies

k6 automatically handles cookies with a VU-scoped cookie jar:

```javascript theme={null}
import http from 'k6/http';
import { check } from 'k6';

export default function() {
  // VU cookie jar automatically manages cookies
  let res = http.get('http://httpbin.org/cookies/set?name=value');
  
  // Access VU cookie jar
  let jar = http.cookieJar();
  let cookies = jar.cookiesForURL(res.url);
  
  check(null, {
    'has cookie': () => cookies.name !== undefined,
  });
  
  // Create local cookie jar
  let localJar = new http.CookieJar();
  localJar.set('http://httpbin.org/cookies', 'custom', 'value123');
  
  http.get('http://httpbin.org/cookies', { jar: localJar });
}
```

## Response Validation with Checks

Use checks to validate responses without failing the test:

```javascript theme={null}
import http from 'k6/http';
import { check } from 'k6';

export default function() {
  let res = http.get('https://quickpizza.grafana.com/api/menu');
  
  check(res, {
    'status is 200': (r) => r.status === 200,
    'status is not 404': (r) => r.status !== 404,
    'response time < 500ms': (r) => r.timings.duration < 500,
    'body size < 10KB': (r) => r.body.length < 10240,
    'has menu items': (r) => r.json('items').length > 0,
    'content type is JSON': (r) => r.headers['Content-Type'].includes('application/json'),
  });
}
```

<Warning>
  Checks don't stop test execution when they fail. Use thresholds if you need to fail the entire test based on check results.
</Warning>

## Common Request Options

| Option        | Type      | Description                                     |
| ------------- | --------- | ----------------------------------------------- |
| `headers`     | object    | Custom HTTP headers                             |
| `tags`        | object    | Custom tags for metrics                         |
| `cookies`     | object    | Request-specific cookies                        |
| `redirects`   | number    | Max redirects to follow                         |
| `timeout`     | string    | Request timeout (e.g., '60s')                   |
| `jar`         | CookieJar | Custom cookie jar                               |
| `compression` | string    | Compression algorithm ('gzip', 'deflate', 'br') |

## Global HTTP Options

Set default options for all HTTP requests:

```javascript theme={null}
export let options = {
  userAgent: 'k6-load-test/1.0',
  maxRedirects: 5,
  insecureSkipTLSVerify: true,
  batch: 10,              // Max parallel requests in batch()
  batchPerHost: 5,        // Max parallel requests per host
  noConnectionReuse: false,
  noVUConnectionReuse: false,
};
```

## Next Steps

* Configure [Test Options](/writing-tests/test-options) for your load test
* Learn about [Tags and Groups](/writing-tests/tags-groups) for organizing metrics
* Explore [Scenarios](/writing-tests/scenarios) for advanced execution patterns
