AlgoLab Blog · 키움증권 · 조회 트러블슈팅 · 2026

키움 REST API 연속조회 — cont-yn·next-key

키움 · 연속조회 2026년 8월 13일 · 알고랩(퀀트웍스)
한 줄 요약

잔고가 50종목인데 20개만 왔다면 API가 고장 난 것이 아니라 나머지를 아직 안 준 것입니다. 키움 REST API는 목록이 길면 나눠서 주고, 다음 페이지 정보를 응답 헤더에 담습니다. cont-ynY면 다음 데이터가 있다는 뜻이고, next-key(최대 50자)가 이어받을 지점입니다. 이 두 값을 다음 요청의 헤더에 그대로 실어 같은 엔드포인트를 다시 부르면 이어집니다.

⚠️ 응답 바디에는 next-key가 없습니다. response.json()이 아니라 response.headers를 보십시오.

키움 REST API를 붙일 때 인증과 주문은 문서대로 하면 대체로 넘어갑니다. 그런데 조회에서 한 번씩 멈추는 지점이 있습니다. 분명히 계좌에 종목이 더 있는데 응답에 일부만 담겨 오는 것입니다.

에러도 없습니다. return_code0이고 return_msg"정상적으로 처리되었습니다"입니다. 정상 응답인데 데이터가 모자란 상태라, 조회 조건을 의심하며 시간을 보내기 쉽습니다.

원인은 하나입니다. 연속조회를 안 돌렸기 때문입니다.

1. 헤더 세 개만 알면 끝난다

키움 REST API 요청·응답 헤더에서 연속조회와 관련된 값은 셋입니다.

헤더방향의미
api-id 요청 8자리 TR코드. 어떤 조회인지 지정 (예: kt00018)
cont-yn 요청 · 응답 연속조회 여부. 응답이 Y면 다음 데이터가 있다
next-key 요청 · 응답 연속조회 키. 최대 50자. 응답 값을 다음 요청에 그대로 세팅

규칙은 문서 표현 그대로입니다. "응답 Header의 연속조회여부 값이 Y일 경우, 다음 데이터 요청 시 응답 Header의 next-key 값을 세팅"합니다. 즉 헤더에서 받아 헤더로 되돌려주는 구조입니다.

요청 ① cont-yn: N next-key: (빈값) 응답 헤더 cont-yn: Y next-key: MTIzNDU... 요청 ② cont-yn: Y next-key: MTIzNDU... cont-yn 이 N 이 될 때까지 반복 응답 헤더 cont-yn 이 N → 마지막 페이지 모아 둔 페이지를 합쳐서 반환
연속조회는 헤더에서 받아 헤더로 되돌려준다

2. 첫 요청 — 평범하게 한 번 부른다

예시로 계좌평가잔고내역요청(kt00018)을 씁니다. 국내주식 계좌 계열이라 경로는 /api/dostk/acnt이고, POST로 조회 조건을 바디에 담아 보냅니다.

import requests

HOST = "https://api.kiwoom.com"      # 모의투자는 별도 도메인
PATH = "/api/dostk/acnt"

headers = {
    "Content-Type": "application/json;charset=UTF-8",
    "authorization": f"Bearer {access_token}",
    "api-id": "kt00018",
    "cont-yn": "N",        # 첫 요청은 연속조회가 아니다
    "next-key": "",        # 비워 둔다
}

body = {
    "qry_dt": "20260813",  # 조회 기준일자
    # 그 밖의 조회 조건은 TR 명세에 따른다
}

res = requests.post(HOST + PATH, headers=headers, json=body, timeout=10)

응답 헤더에는 이런 값들이 실려 옵니다.

>>> {k: res.headers.get(k) for k in ("api-id", "cont-yn", "next-key")}
{'api-id': 'kt00018', 'cont-yn': 'Y', 'next-key': 'MTIzNDU2Nzg5MA=='}

>>> res.json()["return_code"], res.json()["return_msg"]
(0, '정상적으로 처리되었습니다')

여기서 대부분이 멈춥니다. return_code0이라 성공으로 보이고, 바디 JSON에는 next-key라는 키가 없습니다. 그래서 "키움 REST API에는 페이징이 없나 보다"라고 결론 내리고 조회 조건만 계속 바꾸게 됩니다. 정보는 처음부터 헤더에 있었습니다.

3. 두 번째 요청 — 받은 값을 그대로 되돌려준다

바디는 첫 요청과 똑같이 두고, 헤더 두 개만 바꿉니다.

headers["cont-yn"] = res.headers.get("cont-yn")     # "Y"
headers["next-key"] = res.headers.get("next-key")   # 응답에서 받은 값 그대로

res2 = requests.post(HOST + PATH, headers=headers, json=body, timeout=10)

바디의 조회 조건을 같이 바꾸지 마십시오. 연속조회는 같은 조건의 다음 구간을 받는 동작입니다. 기준일자나 조회 구분을 함께 바꾸면 이어받는 지점과 조건이 어긋나 중복이나 누락이 생깁니다. 바뀌는 것은 헤더 두 개뿐입니다.

4. 끝까지 받는 반복 코드

실제로 쓰는 형태는 cont-ynY가 아닐 때까지 도는 반복문입니다. 다만 안전장치 세 개를 같이 넣어야 합니다.

import time

def fetch_all(api_id, body, access_token, max_pages=50, pause=0.2):
    """cont-yn 이 N 이 될 때까지 모든 페이지를 모아서 돌려준다"""
    headers = {
        "Content-Type": "application/json;charset=UTF-8",
        "authorization": f"Bearer {access_token}",
        "api-id": api_id,
        "cont-yn": "N",
        "next-key": "",
    }

    pages, seen_keys = [], set()

    for page in range(max_pages):                     # ① 페이지 상한
        res = requests.post(HOST + PATH, headers=headers,
                            json=body, timeout=10)
        res.raise_for_status()
        data = res.json()

        if data.get("return_code") != 0:              # ② 실패면 즉시 중단
            raise RuntimeError(
                f"{api_id} 실패: {data.get('return_code')} "
                f"{data.get('return_msg')}"
            )

        pages.append(data)

        cont = (res.headers.get("cont-yn") or "N").strip().upper()
        nkey = res.headers.get("next-key") or ""

        if cont != "Y" or not nkey:
            break                                     # 마지막 페이지

        if nkey in seen_keys:                         # ③ 같은 키 재등장 = 무한루프
            raise RuntimeError(f"next-key 반복 감지: {nkey[:12]}...")
        seen_keys.add(nkey)

        headers["cont-yn"] = "Y"
        headers["next-key"] = nkey
        time.sleep(pause)                             # 호출 간격

    return pages

안전장치 세 개는 각각 다른 사고를 막습니다.

장치막는 사고
max_pages 상한 서버가 계속 Y를 주는 상황에서 무한 호출로 한도 소진
return_code 검사 중간 페이지가 실패했는데 빈 데이터를 정상으로 합쳐 버리는 것
seen_keys 중복 검사 같은 next-key가 반복돼 같은 구간을 무한히 다시 받는 것

페이지를 다 받은 뒤에 처리하십시오. 페이지마다 주문을 내거나 무거운 계산을 끼워 넣으면, 조회가 길어질수록 호출량과 실행 시간이 같이 늘어납니다. 모으기와 처리를 분리하면 중간에 끊겨도 재시도가 쉬워집니다.

5. 자주 나는 실수 5가지

실수증상고치는 법
바디에서 next-key를 찾는다 페이징 기능이 없다고 결론 res.headers에서 읽는다
요청 헤더 키에 언더스코어 사용 계속 첫 페이지만 온다 cont_yn이 아니라 cont-yn
첫 요청부터 cont-yn: Y 이어받을 지점이 없어 결과가 어긋남 첫 요청은 N + 빈 next-key
반복 중 바디 조건 변경 중복·누락 데이터 바디 고정, 헤더 둘만 교체
간격 없이 연속 호출 호출 제한에 걸려 중단 간격 + 실패 시 점진적 재시도

마지막 항목은 특히 조심해야 합니다. 연속조회는 짧은 시간에 같은 엔드포인트를 반복 호출하는 작업이라 호출 제한에 가장 먼저 부딪히는 구간입니다. 실제로 거부가 뜨는 경우의 대응은 키움 REST API 429 — 허용된 요청 개수 초과에, 애초에 한도 안에서 돌게 만드는 설계는 API 호출 제한 설계에 정리해 두었습니다.

6. 한국투자증권 KIS와는 방식이 다르다

두 증권사를 함께 붙이는 봇이라면 이 차이를 미리 알아 두는 편이 좋습니다. 같은 "연속조회"라는 이름인데 옮기는 위치가 다릅니다.

키움 REST API한국투자증권 KIS API
다음 페이지 정보 위치 응답 헤더 응답 바디(연속조회 검색조건)
다음 요청에 싣는 곳 요청 헤더 (next-key) 요청 쿼리 파라미터
연속 여부 표시 cont-yn tr_cont
키 형태 단일 키값(최대 50자) 검색조건 값 여러 개

KIS 쪽 구현은 KIS API 잔고조회 연속조회에 따로 정리해 두었습니다. 두 방식을 상위 코드에서 직접 다루면 분기가 지저분해지므로, 증권사별 어댑터 안에 가두고 바깥에는 "전체 목록"만 돌려주는 구조를 권합니다.

🛠️
키움 연동에서 막히셨나요

인증·조회·주문까지 실제로 도는 상태로 만들어 드립니다.

무료 상담 시작하기 →

자주 묻는 질문

next-key는 응답의 어디에 있나요?

응답 헤더입니다. res.json()이 아니라 res.headers.get("next-key")로 꺼내십시오. 함께 오는 cont-ynY면 다음 데이터가 있다는 뜻입니다.

첫 요청에도 cont-yn을 넣어야 하나요?

첫 요청은 cont-yn: N, next-key: ""로 둡니다. 처음부터 Y를 보내면서 키가 비어 있으면 이어받을 지점이 없습니다.

헤더 이름을 cont_yn으로 써도 되나요?

안 됩니다. HTTP 헤더 키는 하이픈cont-yn·next-key입니다. 파이썬 변수명으로 cont_yn을 쓰는 것은 무관하지만 헤더 키에 언더스코어가 들어가면 인식되지 않습니다.

KIS API와 무엇이 다른가요?

키움은 헤더에서 헤더로, KIS는 바디에서 쿼리로 옮깁니다. 연속 표시도 cont-yntr_cont로 다릅니다.

연속조회 중 요청이 거부되면?

즉시 재시도하지 말고 간격을 늘려 가며 다시 시도하십시오. 페이지마다 무거운 작업을 끼우지 말고 모으기와 처리를 분리하는 편이 안전합니다.

확인 캐치. 이 글의 헤더명·TR코드·경로는 2026년 8월 13일 기준 키움증권 REST API 문서를 근거로 작성했습니다. 코드 예시의 next-key 값과 조회 조건 필드는 형식을 보여주기 위한 예시이며, TR별 요청 바디 항목과 응답 필드는 각 TR 명세에 따라 다릅니다. 증권사 API 규격·호출 한도·도메인은 개정될 수 있으므로 구현 전 키움 REST API 공식 문서에서 현재 값을 확인하십시오. 본 글은 기술 자료이며 특정 종목이나 수익률에 대한 예측·권유를 담고 있지 않습니다.

마무리

정리하면 한 줄입니다. 목록이 모자라면 응답 헤더의 cont-yn을 보고, next-key를 그대로 되돌려주면 됩니다. 바디를 아무리 뒤져도 답이 없는 이유는 처음부터 거기에 없었기 때문입니다.

키움 연동, 조회부터 주문까지 만들어 드립니다

연속조회·호출 제한·재시도까지 실제로 도는 상태로 넘겨 드립니다. 24시간 빠른 답변 가능합니다.

무료 상담 시작하기