Lambda 関数 URL(Function URL)は、Lambda 関数に専用の HTTPS の URL を付ける機能です。 API Gateway を作らずに、https://<url-id>.lambda-url.<region>.on.aws の形の URL で関数を呼び出せます。URL の利用自体に追加の料金はかかりません(関数の実行分だけ)。

aws lambda create-function-url-config \
  --function-name my-function \
  --auth-type NONE \
  --cors 'AllowOrigins=https://www.example.com,AllowMethods=GET,POST,MaxAge=300'
設定 値 意味
AuthType NONE 認証なし(公開)。リソースベースポリシーで公開を許可する
AWS_IAM IAM の SigV4 署名つきリクエストだけ受け付ける
InvokeMode BUFFERED(既定) 関数の処理が終わってから返す。応答は最大 6 MB
RESPONSE_STREAM 書いた分から順に返す。応答は最大 200 MB
Cors AllowOrigins など6項目 ブラウザから別のオリジンで呼ぶときの設定
Qualifier エイリアス名か $LATEST URL を付ける対象(番号付きのバージョンには付けられない)

確認環境:AWS CLI 1.46.1(botocore 1.43.62)の create-function-url-config・update-function-url-config・delete-function-url-config・add-permission を、moto 5.2.4 のサーバーモードに --endpoint-url で向けて実行し、CLI が送る API のパス・メソッド・本文を --debug で確かめました。ハンドラは Python 3.11 で、ドキュメントのイベント形式を渡して動かしました。認証・CORS・応答形式・ストリーミング・クォータは AWS のドキュメントで確かめた内容です(確認日 2026年10月13日)。

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Lambda関数URLの使い方|認証・CORS・ストリーミング」

関数 URL を作る(AWS CLI)

1. 関数を用意する

関数 URL は、作成済みの関数に付けます。関数の作成は、関連記事「AWS CLIでLambdaを作成・更新 環境変数とレイヤー」で扱っています。

2. URL を作る:create-function-url-config

aws lambda create-function-url-config \
  --function-name url-demo \
  --auth-type NONE \
  --cors 'AllowOrigins=https://www.example.com,AllowMethods=GET,POST,AllowHeaders=content-type,MaxAge=300'

--debug で見ると、CLI は次の API を呼んでいました。

POST /2021-10-31/functions/url-demo/url
{"AuthType": "NONE", "Cors": {"AllowOrigins": ["https://www.example.com"], "AllowMethods": ["GET", "POST"], "AllowHeaders": ["content-type"], "MaxAge": 300}}

--cors の省略形(Shorthand)では、AllowMethods=GET,POST のように「,」で区切った値がリストになりました。 戻り値の FunctionUrl が、呼び出しに使う URL です。

{
    "FunctionUrl": "https://1f89d7b83e5441fba968aa0c9fd81cba.lambda-url.ap-northeast-1.on.aws",
    "FunctionArn": "arn:aws:lambda:ap-northeast-1:123456789012:function:url-demo",
    "AuthType": "NONE",
    "Cors": { "AllowOrigins": ["https://www.example.com"], "AllowMethods": ["GET", "POST"], "AllowHeaders": ["content-type"], "MaxAge": 300 }
}

(moto が返した値。url-id の部分は作るたびに変わります)

Lambda 開発者ガイドの CLI 例には --cors-config と書かれていますが、AWS CLI 1.46.1 のオプション名は --cors でした。 --cors-config を付けると次のエラーになりました。

Unknown options: --cors-config, AllowOrigins=*

3. 公開するなら権限を2つ足す(AuthType NONE)

NONE でも、リソースベースポリシー(関数側の許可)で公開を許可しないと、403 Forbidden になります。 ドキュメントには「2025年10月から、新しい関数 URL には lambda:InvokeFunctionUrl と lambda:InvokeFunction の両方の権限が必要」とあります。ステートメントは1つずつ別のコマンドで足します。

# 1つめ:関数 URL 経由の呼び出しを許可
aws lambda add-permission \
  --function-name url-demo \
  --statement-id FunctionURLAllowPublicAccess \
  --action lambda:InvokeFunctionUrl \
  --principal '*' \
  --function-url-auth-type NONE

# 2つめ:関数の実行を、関数 URL 経由に限って許可
aws lambda add-permission \
  --function-name url-demo \
  --statement-id FunctionURLInvokeAllowPublicAccess \
  --action lambda:InvokeFunction \
  --principal '*' \
  --invoked-via-function-url

2つめのコマンドで CLI が送った本文は次の通りでした。--invoked-via-function-url は InvokedViaFunctionUrl: true になります。

POST /2015-03-31/functions/url-demo/policy
{"StatementId": "...", "Action": "lambda:InvokeFunction", "Principal": "*", "InvokedViaFunctionUrl": true}

ドキュメントに載っている、NONE のときにできるポリシーです。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "FunctionURLAllowPublicAccess",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "lambda:InvokeFunctionUrl",
      "Resource": "arn:aws:lambda:us-east-2:123456789012:function:my-function",
      "Condition": { "StringEquals": { "lambda:FunctionUrlAuthType": "NONE" } }
    },
    {
      "Sid": "FunctionURLInvokeAllowPublicAccess",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "lambda:InvokeFunction",
      "Resource": "arn:aws:lambda:us-east-2:123456789012:function:my-function",
      "Condition": { "Bool": { "lambda:InvokedViaFunctionUrl": "true" } }
    }
  ]
}

lambda:InvokedViaFunctionUrl の条件があるので、2つめのステートメントは「関数 URL 経由の呼び出し」に限られます。 Invoke API での直接呼び出しまで公開するものではありません。zsh では * がファイル名に展開されるため、--principal '*' と引用符で囲みます。

4. 変更・確認・削除

# 認証や呼び出し方式を変える
aws lambda update-function-url-config \
  --function-name url-demo \
  --auth-type AWS_IAM \
  --invoke-mode RESPONSE_STREAM

# 今の設定を見る
aws lambda get-function-url-config --function-name url-demo

# 削除する
aws lambda delete-function-url-config --function-name url-demo
コマンド CLI が呼んだ API
create-function-url-config POST /2021-10-31/functions/{関数名}/url
update-function-url-config PUT /2021-10-31/functions/{関数名}/url
delete-function-url-config DELETE /2021-10-31/functions/{関数名}/url
add-permission POST /2015-03-31/functions/{関数名}/policy

--qualifier live を付けると、クエリ文字列 ?Qualifier=live が付き、エイリアス live 用の URL になりました。--auth-type を付けないと、送る前に CLI が the following arguments are required: --auth-type で止まりました。

ドキュメントによると、削除した URL は元に戻せず、作り直すと別の URL になります。 また、NONE の URL を削除しても、足したリソースベースポリシーは残ります。

AuthType:NONE と AWS_IAM

NONE AWS_IAM
認証 Lambda は認証しない SigV4 で署名したリクエストだけ通す
必要な許可 リソースベースポリシーで Principal: "*" を許可 呼び出す側の IAM ポリシー(他アカウントなら関数側のポリシーも)
必要なアクション lambda:InvokeFunctionUrl と lambda:InvokeFunction 同じ2つ
向いている場面 Webhook の受け口、公開 API(関数の中で独自に認証) 社内のサービス間、CloudFront からの呼び出し
requestContext.authorizer null 呼び出し元の iam(userArn など)が入る

AWS_IAM の URL を curl で呼ぶときは、--aws-sigv4 で署名します。 AWS のチュートリアルの形です(サービス名は lambda)。

curl --request GET "https://<url-id>.lambda-url.us-east-1.on.aws/" \
  --user "AKIAIOSFODNN7EXAMPLE" \
  --aws-sigv4 "aws:amz:us-east-1:lambda" \
  --no-buffer

--user にアクセスキー ID を渡すと、シークレットアクセスキーを聞かれます。

イベントの形式(関数が受け取るもの)

関数 URL のイベントは、API Gateway HTTP API のペイロード形式 2.0 と同じ形です。 ドキュメントの例から主な項目を抜き出しました。

{
  "version": "2.0",
  "routeKey": "$default",
  "rawPath": "/my/path",
  "rawQueryString": "parameter1=value1&parameter1=value2&parameter2=value",
  "cookies": ["cookie1", "cookie2"],
  "headers": { "header1": "value1", "header2": "value1,value2" },
  "queryStringParameters": { "parameter1": "value1,value2", "parameter2": "value" },
  "requestContext": {
    "accountId": "123456789012",
    "apiId": "<urlid>",
    "authorizer": { "iam": { "userArn": "arn:aws:iam::111122223333:user/example-user" } },
    "domainName": "<url-id>.lambda-url.us-west-2.on.aws",
    "http": {
      "method": "POST",
      "path": "/my/path",
      "protocol": "HTTP/1.1",
      "sourceIp": "123.123.123.123",
      "userAgent": "agent"
    },
    "requestId": "id",
    "time": "12/Mar/2020:19:03:58 +0000",
    "timeEpoch": 1583348638390
  },
  "body": "Hello from client!",
  "pathParameters": null,
  "isBase64Encoded": false,
  "stageVariables": null
}
読みたいもの 場所
メソッド event["requestContext"]["http"]["method"]
パス event["rawPath"](URL の後ろはすべて関数に届く)
クエリ event["queryStringParameters"](同じ名前は「,」でつながる)
ヘッダー event["headers"](同じ名前は「,」でつながる)
本文 event["body"]。バイナリなら Base64 で isBase64Encoded: true
呼び出し元の IP event["requestContext"]["http"]["sourceIp"]

pathParameters と stageVariables は null です。 ルーティング(/users/{id} のような分け方)は無いので、rawPath を見て関数の中で分けます。

応答の形式(関数が返すもの)

{
  "statusCode": 201,
  "headers": { "Content-Type": "application/json", "My-Custom-Header": "Custom Value" },
  "body": "{ \"message\": \"Hello, world!\" }",
  "cookies": [
    "Cookie_1=Value1; Expires=21 Oct 2021 07:48 GMT",
    "Cookie_2=Value2; Max-Age=78000"
  ],
  "isBase64Encoded": false
}

statusCode を含まない JSON を返すと、Lambda が形を推測します。 ドキュメントの説明です。

関数の戻り値 クライアントが受け取るもの
{"statusCode": 201, "body": "..."} 指定どおり(statusCode は 100〜599)
{"message": "Hello, world!"}(statusCode なし) 200、content-type: application/json、本文は戻り値の JSON
"Hello, world!"(文字列) 200、content-type: application/json、本文は "Hello, world!"

Cookie は Set-Cookie ヘッダーではなく cookies の配列で返します。 Lambda が set-cookie ヘッダーに変換します。

Python のハンドラ例(コピペ用)

import base64
import json


def lambda_handler(event, context):
    http = event["requestContext"]["http"]
    body = event.get("body") or ""
    if event.get("isBase64Encoded"):
        body = base64.b64decode(body).decode("utf-8")

    return {
        "statusCode": 200,
        "headers": {"Content-Type": "application/json"},
        "cookies": ["visited=1; Max-Age=3600; Secure; HttpOnly"],
        "body": json.dumps({
            "method": http["method"],
            "path": event["rawPath"],
            "query": event.get("queryStringParameters"),
            "body": body,
            "sourceIp": http["sourceIp"],
        }, ensure_ascii=False),
    }

rawPath が /orders、クエリが page=2、Base64 の本文 {"item":"本"} のイベントを渡すと、次の値が返りました。

{
  "statusCode": 200,
  "headers": { "Content-Type": "application/json" },
  "cookies": ["visited=1; Max-Age=3600; Secure; HttpOnly"],
  "body": "{\"method\": \"POST\", \"path\": \"/orders\", \"query\": {\"page\": \"2\"}, \"body\": \"{\\\"item\\\":\\\"本\\\"}\", \"sourceIp\": \"203.0.113.10\"}"
}

Python の handler の基本とローカルでのテストは、関連記事「AWS Lambda Python入門|3.14対応handler例とローカルテスト」で扱っています。

CORS の設定

ブラウザから別のオリジン(ドメイン)の関数 URL を呼ぶときは、関数 URL の Cors を設定します。 設定すると、Lambda がすべての応答に CORS のヘッダーを付けます。

設定項目 付くヘッダー 例
AllowOrigins Access-Control-Allow-Origin https://www.example.com、*
AllowMethods Access-Control-Allow-Methods GET、POST、*
AllowHeaders Access-Control-Allow-Headers content-type、X-Custom-Header
ExposeHeaders Access-Control-Expose-Headers X-Request-Id
AllowCredentials Access-Control-Allow-Credentials true(CLI のヘルプでは既定 false)
MaxAge Access-Control-Max-Age 秒数。300

MaxAge の既定値は、AWS CLI 1.46.1 のヘルプでは「0(ブラウザはキャッシュしない)」、開発者ガイドの表では「5 (default)」と書かれていました。値を明示すると迷いません。

aws lambda update-function-url-config \
  --function-name url-demo \
  --cors '{"AllowOrigins":["https://www.example.com"],"AllowMethods":["GET","POST"],"AllowHeaders":["content-type"],"MaxAge":300}'

関数の中でも CORS ヘッダーを返すと重複する

ドキュメントでは、関数 URL の CORS 設定と、関数が返す CORS ヘッダーの両方があるときの動きが、リクエストの種類で違うと説明されています。

リクエスト 応答の CORS ヘッダー
プリフライト(OPTIONS) 関数 URL の設定だけ
GET・POST など 関数 URL の設定と関数の戻り値の両方(重複する)

重複すると、ブラウザで次のエラーになります(ドキュメントの例)。

The 'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed

CORS は関数 URL の設定に寄せ、関数のコードからは返さないのが、ドキュメントの勧めです。CORS エラーの読み方は、関連記事「CORSエラーの原因と解決方法|エラーメッセージ別に解説」で扱っています。

レスポンスストリーミング

RESPONSE_STREAM にすると、関数が書いた分から順にクライアントへ送られます。 生成 AI の文章を少しずつ表示する、大きなファイルを返す、といった場面で使います。

項目 BUFFERED RESPONSE_STREAM
内部で使う API Invoke InvokeWithResponseStream
応答の最大サイズ 6 MB 200 MB
帯域 ― 最初の 6 MB は制限なし、その後は最大 2 MBps
対応ランタイム すべて Node.js のマネージドランタイム(ほかはカスタムランタイムか Lambda Web Adapter)
VPC に置いた関数 使える 関数 URL ではストリーミングできない
aws lambda update-function-url-config \
  --function-name my-streaming-function \
  --invoke-mode RESPONSE_STREAM

Node.js のハンドラは、awslambda.streamifyResponse() で包みます。awslambda は Lambda の Node.js ランタイムが用意するグローバルなオブジェクトで、import はいりません。状態コードとヘッダーは awslambda.HttpResponseStream.from() で付けます。AWS のチュートリアルの形です。

// index.mjs
export const handler = awslambda.streamifyResponse(
  async (event, responseStream, _context) => {
    const metadata = {
      statusCode: 200,
      headers: { 'Content-Type': 'text/plain; charset=utf-8' },
    }
    // 包んだあとのストリームを使う(包む前のものを使わないよう上書きする)
    responseStream = awslambda.HttpResponseStream.from(responseStream, metadata)

    for (let i = 0; i < 3; i++) {
      responseStream.write(`Hello ${i}\n`)
      await new Promise((r) => setTimeout(r, 1000))
    }
    responseStream.end()
    await responseStream.finished()
  },
)
curl --no-buffer "https://<url-id>.lambda-url.ap-northeast-1.on.aws/"

ドキュメントの注意点です。

  • 書き終わったら responseStream.end() で閉じる(pipeline() を使えば自動で閉じる)。
  • Node.js 24 からは、ハンドラが返ったあとに残った Promise を Lambda が待たない。非同期の処理は await する。
  • クライアントが途中で切っても、関数は止まらず、実行した時間の分の料金がかかる。
  • コンソールのテストでは、応答はバッファされて表示される。

API Gateway との比較

Lambda のドキュメント「HTTP リクエストで関数を呼ぶ方法の選び方」と、各サービスのクォータのページの内容を表にしました。

項目 関数 URL API Gateway(HTTP API) API Gateway(REST API)
料金 URL 自体は無料(関数の実行分だけ) 呼び出し回数・転送量 呼び出し回数・転送量・キャッシュ
待てる時間 関数のタイムアウト(最大 900 秒) 最大 30 秒 50 ミリ秒〜29 秒(リージョン・プライベートは引き上げ可)
本文のサイズ 6 MB(ストリーミングは応答 200 MB) 10 MB 10 MB
認証 NONE か IAM IAM・JWT・Lambda オーソライザー IAM・Cognito・Lambda オーソライザー・API キー
ルーティング なし(rawPath を関数で見る) ルートごとに関数を分けられる リソース・メソッドごと
入力チェック・変換 なし ― リクエストの検証・マッピングテンプレート
流量の制限 関数の同時実行数(予約同時実行 ×10 が最大 RPS) ステージ・ルート単位 ステージ・メソッド単位、使用量プラン
独自ドメイン なし(CloudFront を前に置く方法がある) あり あり
WAF ― ― あり
CORS 設定だけで付く 設定で付く 自分で設定(OPTIONS メソッドなど)

(「―」はドキュメントの比較で触れられていない項目)

ドキュメントの勧めは、関数 URL は「簡単なアプリや試作で、認証と入出力が基本的なもので足り、コストと手間を抑えたい」とき、API Gateway は「本番の大きな規模や、独自ドメイン・豊富な認証・流量制限・キャッシュ・変換などが要る」ときです。

29 秒(REST API)・30 秒(HTTP API)を超える処理を同期で返したいときは、関数 URL が候補になります。 API Gateway の REST API と HTTP API の違いは、関連記事「API Gateway Lambda|REST APIとHTTP APIの違い」、独自の認証は関連記事「API Gateway Lambdaオーソライザーの作り方|トークン型とリクエスト型」で扱っています。

SAM・CloudFormation で書く

SAM では FunctionUrlConfig を書きます。AuthType は必須、Cors と InvokeMode は省略できます(InvokeMode の既定は BUFFERED)。

HelloWorldFunction:
  Type: AWS::Serverless::Function
  Properties:
    CodeUri: hello_world/
    Handler: index.handler
    Runtime: nodejs22.x
    FunctionUrlConfig:
      AuthType: AWS_IAM
      InvokeMode: RESPONSE_STREAM
      Cors:
        AllowOrigins:
          - https://www.example.com
        AllowMethods:
          - GET

Outputs:
  MyFunctionUrlEndpoint:
    Value:
      Fn::GetAtt: HelloWorldFunctionUrl.FunctionUrl

SAM のドキュメントでは、URL は既定で $LATEST に付き、AutoPublishAlias を設定するとそのエイリアスに付く、と説明されています。CloudFormation で直接書くときは AWS::Lambda::Url(AuthType・TargetFunctionArn が必須)を使います。

よくあるつまずき

症状 原因 直し方
NONE なのに 403 Forbidden リソースベースポリシーに許可が無い InvokeFunctionUrl と InvokeFunction の2つを add-permission
AWS_IAM で 403 署名が無い・権限が足りない --aws-sigv4、呼び出す側に2つのアクションを許可
429 が返る 予約同時実行の上限、または予約同時実行が 0 同時実行の設定を見直す(0 は URL を止める方法として案内されている)
Access-Control-Allow-Origin が2つ付く 関数 URL の CORS と関数の戻り値の両方 関数の戻り値から CORS ヘッダーを外す
Unknown options: --cors-config オプション名の誤り --cors
番号付きバージョンに URL を付けられない 仕様(エイリアスか $LATEST だけ) エイリアスを作って --qualifier
ストリーミングにならない InvokeMode が BUFFERED、VPC の関数、コンソールのテスト RESPONSE_STREAM にし、curl --no-buffer で確かめる

よくある質問

Q. 独自ドメインで公開できますか。 A. 関数 URL 自体には独自ドメインの設定がありません。CloudFront を前に置き、オリジンに関数 URL を指定する構成がよく使われます。

Q. VPC の中からだけ呼びたいです。 A. ドキュメントでは、関数 URL はパブリックなインターネットからだけ使え、AWS PrivateLink には対応していないとされています。閉じた経路が要るなら、API Gateway のプライベート API などを検討します。

Q. URL は変わりますか。 A. 作成した URL は変わりません。削除して作り直すと、別の URL になります。

まとめ

  • 関数 URL は create-function-url-config 1つで HTTPS の URL が付く。URL 自体は無料
  • AuthType は NONE か AWS_IAM。2025年10月から InvokeFunctionUrl と InvokeFunction の両方の許可が必要
  • イベントは ペイロード形式 2.0。ルーティングは無いので rawPath で分ける
  • CORS は関数 URL 側で設定し、関数のコードからは返さない
  • RESPONSE_STREAM で応答 200 MB まで。Node.js は awslambda.streamifyResponse
  • 30 秒を超える同期処理は関数 URL、独自ドメイン・豊富な認証・流量制限は API Gateway

参考・出典

確認日はいずれも 2026年10月13日です。

  • AWS Lambda デベロッパーガイド「Creating and managing Lambda function URLs」:https://docs.aws.amazon.com/lambda/latest/dg/urls-configuration.html
  • AWS Lambda デベロッパーガイド「Control access to Lambda function URLs」:https://docs.aws.amazon.com/lambda/latest/dg/urls-auth.html
  • AWS Lambda デベロッパーガイド「Invoking Lambda function URLs」:https://docs.aws.amazon.com/lambda/latest/dg/urls-invocation.html
  • AWS Lambda デベロッパーガイド「Response streaming for Lambda functions」:https://docs.aws.amazon.com/lambda/latest/dg/configuration-response-streaming.html
  • AWS Lambda デベロッパーガイド「Writing response streaming-enabled Lambda functions」:https://docs.aws.amazon.com/lambda/latest/dg/config-rs-write-functions.html
  • AWS Lambda デベロッパーガイド「Tutorial: Creating a response streaming Lambda function with a function URL」:https://docs.aws.amazon.com/lambda/latest/dg/response-streaming-tutorial.html
  • AWS Lambda デベロッパーガイド「Select a method to invoke your Lambda function using an HTTP request」:https://docs.aws.amazon.com/lambda/latest/dg/furls-http-invoke-decision.html
  • AWS Lambda デベロッパーガイド「Lambda quotas」:https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-limits.html
  • Amazon API Gateway デベロッパーガイド「Quotas for configuring and running a REST API」:https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-execution-service-limits-table.html
  • Amazon API Gateway デベロッパーガイド「Quotas for configuring and running HTTP APIs」:https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-quotas.html
  • AWS SAM デベロッパーガイド「FunctionUrlConfig」:https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-function-functionurlconfig.html

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Lambda関数URLの使い方|認証・CORS・ストリーミング」

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?