{
  "schema_version": 2,
  "id": "develop/clients/hiredis/issue-commands",
  "title": "Issue commands",
  "url": "https://redis.io/docs/latest/develop/clients/hiredis/issue-commands/",
  "summary": "Construct commands and send them to the Redis server.",
  "tags": [
    "docs",
    "develop",
    "stack",
    "oss",
    "rs",
    "rc",
    "oss",
    "kubernetes",
    "clients"
  ],
  "last_updated": "2026-09-09T11:06:49+01:00",
  "page_type": "content",
  "content_hash": "e901d457a5a73b33a53663e1aad376b8ee1977404332d706af8b8bc44634f302",
  "sections": [
    {
      "id": "overview",
      "title": "Overview",
      "role": "overview",
      "text": "Unlike the other [client libraries](https://redis.io/docs/latest/develop/clients),\n`hiredis` doesn't provide an extensive API to construct the many different\nRedis [commands](/commands). However, it does provide a lightweight and\nflexible API to help you construct commands and parse their replies from\nyour own code.\n\nThe sections below describe the available functions in\ndetail."
    },
    {
      "id": "construct-synchronous-commands",
      "title": "Construct synchronous commands",
      "role": "content",
      "text": "Use the `redisCommand()` function to send commands to the server:\n\n[code example]\n\nThis function receives a `redisContext` pointer and a pointer\nto a string containing the command (see\n[Connect](https://redis.io/docs/latest/develop/clients/hiredis/connect)\nto learn how to obtain the context pointer). The command text is the\nsame as the equivalent [`redis-cli`](https://redis.io/docs/latest/develop/tools/cli)\ncommand. For example, to issue the command:\n\n[code example]\n\nyou would use the following command with an existing `redisContext* c`:\n\n[code example]\n\nSee the [Command reference](/commands) for examples\nof CLI commands that you can use with `hiredis`. Most code examples\nin other sections of the docs also have a CLI tab showing\ncommand sequences that are equivalent to the code.\n\nThe command string is interpreted in a similar way to the format\nstring for `printf()`, so you can easily interpolate string values from\nyour code into the command with the `%s` format specifier:\n\n[code example]\n\nYou may need to include binary data in the command (for example, to store\n[vector embeddings](https://redis.io/docs/latest/develop/ai/search-and-query/vectors)\nin fields of a [hash](https://redis.io/docs/latest/develop/data-types/hashes)) object.\nTo do this, use the `%b` format specifier and pass a pointer to the\ndata buffer, followed by a `size_t` value indicating its length in bytes.\nAs the example below shows, you can freely mix `%s` and `%b` specifiers\nin the same format string. Also, you can use the sequence `%%` to\ndenote a literal percent sign, but the other `printf()` specifiers,\nsuch as `%d`, are not supported.\n\n[code example]\n\nThe `redisCommand()` function has a variant called `redisCommandArgv()`:\n\n[code example]\n\nThis doesn't take a format string but instead builds the command from an array\nof strings passed in the `argv` parameter.\n\nUse the `argc` value to\nspecify the length of this array and the `argvlen` array to specify\nthe lengths of each of the strings in the array. If you pass `NULL`\nfor `argvlen` then the function will attempt to use `strlen()` to\nget the length of each string. However, this will not work if any of\nthe strings contains binary data, so you should pass `argvlen`\nexplicitly in this case. The example below shows how to use\n`redisCommandArgv()` with a simple command:\n\n[code example]"
    },
    {
      "id": "construct-asynchronous-commands",
      "title": "Construct asynchronous commands",
      "role": "content",
      "text": "Use the `redisAsyncCommand()` and `redisAsyncCommandArgv()`\nfunctions to send commands to the server asynchronously:\n\n[code example]\n\nThese work the same way as `redisCommand()` and `redisCommandArgv()`\n(see [Construct synchronous commands](#construct-synchronous-commands)\nabove) but they have two extra parameters. The first is a pointer to\na optional callback function and the second is a pointer to your own\ncustom data, which will be passed to the callback when it\nexecutes. Pass `NULL` for both of these pointers if you don't need\nto use them.\n\nThe callback has the following signature:\n\n[code example]\n\nThe first parameter is the asynchronous connection context and\nthe second is a pointer to the reply object. Use a cast to\n`(redisReply *)` to access the reply in the usual way (see \n[Handle command replies](https://redis.io/docs/latest/develop/clients/hiredis/handle-replies)\nfor a full description of `redisReply`). The last parameter\nis the custom data pointer that you supplied during the\n`redisAsyncCommand()` call. This is passed to your function\nwithout any modification.\n\nThe example below shows how you can use `redisAsyncCommand()` with\nor without a reply callback:\n\n[code example]\n\nNote that you should normally disconnect asynchronously from a\ncallback when you have finished using the connection.\nUse `redisAsyncDisconnect()` to disconnect gracefully, letting\npending commands execute and activate their callbacks.\nUse `redisAsyncFree()` to disconnect immediately. If you do this then\nany pending callbacks from commands that have already executed will be\ncalled with a `NULL` reply pointer."
    },
    {
      "id": "command-replies",
      "title": "Command replies",
      "role": "syntax",
      "text": "The information in the `redisReply` object has several formats,\nand the format for a particular reply depends on the command that generated it.\nSee\n[Handle replies](https://redis.io/docs/latest/develop/clients/hiredis/handle-replies)\nto learn about the different reply formats and how to use them."
    }
  ],
  "examples": [
    {
      "id": "construct-synchronous-commands-ex0",
      "language": "c",
      "code": "void *redisCommand(redisContext *c, const char *format, ...);",
      "section_id": "construct-synchronous-commands"
    },
    {
      "id": "construct-synchronous-commands-ex1",
      "language": "plaintext",
      "code": "SET foo bar",
      "section_id": "construct-synchronous-commands"
    },
    {
      "id": "construct-synchronous-commands-ex2",
      "language": "c",
      "code": "redisReply *reply = redisCommand(c, \"SET foo bar\");",
      "section_id": "construct-synchronous-commands"
    },
    {
      "id": "construct-synchronous-commands-ex3",
      "language": "c",
      "code": "char *myKeyNumber = \"1\";\nchar *myValue = \"Hello\";\n\n// This issues the command 'SET key:1 Hello'.\nredisReply *reply = redisCommand(c, \"SET key:%s %s\", myKeyNumber, myValue);",
      "section_id": "construct-synchronous-commands"
    },
    {
      "id": "construct-synchronous-commands-ex4",
      "language": "c",
      "code": "char *entryNumber = \"1\";\nchar *embedding = \"<binary data>\";\nchar *url = \"https://redis.io/\";\nsize_t embLength = 13;\n\nredisReply *reply = redisCommand(c,\n    \"HSET entry:%s embedding %b  url %s\",\n    entryNumber,\n    embedding, embLength,\n    url\n);",
      "section_id": "construct-synchronous-commands"
    },
    {
      "id": "construct-synchronous-commands-ex5",
      "language": "c",
      "code": "void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);",
      "section_id": "construct-synchronous-commands"
    },
    {
      "id": "construct-synchronous-commands-ex6",
      "language": "c",
      "code": "const char *argv[3] = { \"SET\", \"greeting\", \"hello\"};\nint argc = 3;\nconst size_t argvlen[] = {3, 8, 5};\n\nredisReply *reply = redisCommandArgv(c, argc, argv, argvlen);",
      "section_id": "construct-synchronous-commands"
    },
    {
      "id": "construct-asynchronous-commands-ex0",
      "language": "c",
      "code": "#include <hiredis/async.h>\n    .\n    .\n    .\nint redisAsyncCommand(\n  redisAsyncContext *ac, redisCallbackFn *fn, void *privdata,\n  const char *format, ...);\nint redisAsyncCommandArgv(\n  redisAsyncContext *ac, redisCallbackFn *fn, void *privdata,\n  int argc, const char **argv, const size_t *argvlen);",
      "section_id": "construct-asynchronous-commands"
    },
    {
      "id": "construct-asynchronous-commands-ex1",
      "language": "c",
      "code": "void(redisAsyncContext *c, void *reply, void *privdata);",
      "section_id": "construct-asynchronous-commands"
    },
    {
      "id": "construct-asynchronous-commands-ex2",
      "language": "c",
      "code": "// The callback expects the key for the data in the `privdata`\n// custom data parameter.\nvoid getCallback(redisAsyncContext *c, void *r, void *privdata) {\n    redisReply *reply = r;\n    char *key = privdata;\n\n    if (reply == NULL) {\n        if (c->errstr) {\n            printf(\"errstr: %s\\n\", c->errstr);\n        }\n        return;\n    }\n\n    printf(\"Key: %s, value: %s\\n\", key, reply->str);\n\n    /* Disconnect after receiving the reply to GET */\n    redisAsyncDisconnect(c);\n}\n    .\n    .\n    .\n\n// Key and string value to pass to `SET`.\nchar *key = \"testkey\";\nchar *value = \"testvalue\";\n\n// We aren't interested in the simple status reply for\n// `SET`, so use NULL for the callback and custom data\n// pointers.\nredisAsyncCommand(c, NULL, NULL, \"SET %s %s\", key, value);\n\n// The reply from `GET` is essential, so set a callback\n// to retrieve it. Also, pass the key to the callback\n// as the custom data.\nredisAsyncCommand(c, getCallback, key, \"GET %s\", key);",
      "section_id": "construct-asynchronous-commands"
    }
  ]
}
